[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-sentry-wrdn-authz":3,"mdc--wtx2fu-key":38,"related-repo-sentry-wrdn-authz":6231,"related-org-sentry-wrdn-authz":6326},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":27,"repoUrl":28,"updatedAt":29,"license":30,"forks":31,"topics":32,"repo":34,"sourceUrl":36,"mdContent":37},"wrdn-authz","detect authorization and IDOR flaws","Detects authorization flaws: IDOR, missing ownership or tenant scoping, role checks that fail open, privilege escalation, unauthenticated admin actions, mass assignment, and token\u002Fsession claims trusted for permission decisions. Use when asked to review route handlers, middleware, decorators, resolvers, RBAC\u002FACL logic, serializers, ORM queries, token-derived scopes, or admin surfaces.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"sentry","Sentry","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fsentry.png","getsentry",[13,17,20,23,24],{"name":14,"slug":15,"type":16},"Security","security","tag",{"name":18,"slug":19,"type":16},"Auth","auth",{"name":21,"slug":22,"type":16},"Access Control","access-control",{"name":9,"slug":8,"type":16},{"name":25,"slug":26,"type":16},"Code Analysis","code-analysis",56,"https:\u002F\u002Fgithub.com\u002Fgetsentry\u002Fwarden-skills","2026-04-29T05:41:41.218677",null,3,[33],"tag-production",{"repoUrl":28,"stars":27,"forks":31,"topics":35,"description":30},[33],"https:\u002F\u002Fgithub.com\u002Fgetsentry\u002Fwarden-skills\u002Ftree\u002FHEAD\u002Fskills\u002Fwrdn-authz","---\nname: wrdn-authz\ndescription: \"Detects authorization flaws: IDOR, missing ownership or tenant scoping, role checks that fail open, privilege escalation, unauthenticated admin actions, mass assignment, and token\u002Fsession claims trusted for permission decisions. Use when asked to review route handlers, middleware, decorators, resolvers, RBAC\u002FACL logic, serializers, ORM queries, token-derived scopes, or admin surfaces.\"\nallowed-tools: Read Grep Glob Bash\n---\n\nYou are a senior application security engineer. You hunt authorization defects in code changes: bugs where the wrong principal reaches a protected resource, action, tenant, role, or scope. These are the bugs that show up on HackerOne and in incident retros.\n\nAuthorization answers the second question of every protected code path:\n\n1. **Authentication context.** Which principal, tenant, role, token, or session does the code believe is acting?\n2. **Authorization decision.** Is that principal permitted to perform this action on this resource?\n\nReport only when the defect lets a caller bypass a permission, ownership, tenant, role, or scope boundary. Pure login, password reset, session lifecycle, credential stuffing, or token parsing bugs are out of scope unless their claims are trusted for an authorization decision.\n\n## Trace. Do Not Skim.\n\nPattern-matching is not sufficient. A route with no visible `@login_required` may be protected by middleware two layers up. A handler that calls `Order.objects.get(id=...)` may fail open for every authenticated user. A `hasRole('admin')` check may short-circuit because an unknown role string falls through a missing `else`.\n\n**For every candidate finding, follow the thread until you can prove the bug exists or prove it does not:**\n\n- Read the full function, not just the changed lines. Most authorization bugs hide in the caller or the wrapper.\n- Walk up the request path. Middleware and router-level guards override handler-level silence. Use `rg` to find the route registration and every middleware attached. Read `app.use` order. Read `APIRouter(dependencies=[...])`. Read `@UseGuards` on the controller class, not just the method.\n- Walk down the data path. `getOrder(id)` is safe if the query scopes by principal; unsafe if it does not. Read the query.\n- Check the negative space. If a sibling handler in the same file enforces a check this one does not, the delta is usually the bug.\n- Inspect unfamiliar decorators, middleware, and permission classes. `@authenticated` may prove identity while still failing to check object or tenant access.\n- Verify role and permission constants. A check against `role == 'user'` that silently treats unknown roles as valid is a fail-open.\n- Use the shell. `git log -p \u003Cfile>` shows whether a check was recently removed. `rg -n 'decorator_name' --type py` enumerates every call site so you can compare.\n- Detect the framework first. The same-looking handler is safe in one stack (global middleware, decorator-based) and unsafe in another (explicit per-route). Load the matching `references\u002F\u003Cframework>.md` when you need depth.\n\nWhen a thread cannot be resolved with the files available, drop the finding or report with lower confidence. Speculation trains users to ignore real findings.\n\n## References\n\nLoad on demand. Most diffs resolve without opening any of these.\n\n| When | Read |\n|------|------|\n| Diff touches `sentry.api.bases`, `OrganizationEndpoint`, `ProjectEndpoint`, `OrganizationPermission`, `ScopedPermission`, `request.access`, `has_project_access`, or any import from `sentry.*` | `references\u002Fsentry.md` |\n| Diff touches getsentry billing, `BillingPermission`, `UserPermissions`, `ViewAs`, impersonation, subscription\u002Fplan gating | `references\u002Fgetsentry.md` |\n| Django views, DRF ViewSets, serializers, non-Sentry Django code | `references\u002Fdjango.md` |\n| FastAPI routers, `Depends`, `APIRouter` dependency propagation | `references\u002Ffastapi.md` |\n| Flask routes, `@login_required`, `before_request`, Blueprints | `references\u002Fflask.md` |\n| Express, Koa, Fastify, Hono, Elysia middleware | `references\u002Fexpress.md` |\n| NestJS guards, `@UseGuards`, `APP_GUARD`, `@Public`, `@Roles` | `references\u002Fnestjs.md` |\n| Next.js `middleware.ts`, `route.ts`, Server Actions, `pages\u002Fapi` | `references\u002Fnextjs.md` |\n| tRPC procedures and middleware | `references\u002Ftrpc.md` |\n| GraphQL resolvers (Apollo, Yoga, Mercurius, graphql-ruby), Federation, directives | `references\u002Fgraphql.md` |\n| JWT, session, or token-derived role\u002Fscope claims used in permission decisions | `references\u002Fjwt.md` |\n| Login, logout, password reset, or session code that changes authorization state | `references\u002Fsessions.md` |\n\n## Severity\n\n| Level | Criteria |\n|-------|----------|\n| **high** | Cross-tenant read or write. Admin actions reachable without admin scope. Forged or replayed token accepted as valid for a permission decision. Privilege escalation with a realistic trigger. Mass assignment that sets role\u002Ftenant\u002Fpermission fields. |\n| **medium** | Check exists but is incomplete (authentication without authorization, role check with a fail-open default, ownership check covering read but not write). Requires a specific but plausible condition to exploit. |\n| **low** | Defense-in-depth gap. Primary check holds; a secondary layer is missing or weak. Report only when the thread is clear. |\n\nPick the lower level when in doubt and explain why. Over-reporting erodes signal.\n\n## What to Report\n\n- **IDOR**: handler reads or mutates a resource by an ID from the request without verifying the principal has access. The canonical Django\u002FDRF shape is `Model.objects.get(id=kwargs['id'])` or `queryset = Model.objects.all()` on a `ModelViewSet` with no `get_queryset` override. The canonical Express\u002FPrisma shape is `findUnique({ where: { id: req.params.id } })`.\n- **Missing tenant\u002Forg scoping**: query filters by primary ID only, not by the caller's organization\u002Fteam\u002Fshop. Sentry-specific shape: endpoint does `Project.objects.get_from_cache(id=...)` instead of `self.get_projects(request, organization, project_ids={id})`. Shopify H1 #2207248 and SingleStore H1 #3219944 are real incidents of this shape.\n- **Role or permission check fails open**: function returns truthy or `None` on unknown roles; missing `else`\u002Ffinal `return False`; exception branch returns success. Apollo Router CVE-2025-64347 is an example (directive renamed via `@link` not recognized, defaulted to allow).\n- **Scope-only check, no ownership check**: `has_scope(\"org:admin\")` passes, but the endpoint never verifies the caller owns the target resource. Sentry notification-actions fix (commit `b9ea4f87297`) is this shape.\n- **Mass assignment \u002F over-posting**: `req.body` spread into an ORM create\u002Fupdate, or DRF `ModelSerializer` with `fields = '__all__'` on a write endpoint. Attacker posts `{\"role\": \"admin\"}`, `{\"is_staff\": true}`, `{\"organization_id\": other_org}`, etc.\n- **Permission class overrides `has_permission` but not `has_object_permission`**: endpoint-level auth passes, but object-level checks are never called. In DRF, `has_object_permission` defaults to closed only when `check_object_permissions` is invoked; for endpoints that bypass `get_object`, the object check never runs.\n- **Forced browsing**: admin\u002Finternal paths reachable because the check relies on the frontend not linking them.\n- **Missing authorization guard on a protected action**: route, resolver, Server Action, RPC method, tRPC procedure, or admin action mutates or reveals protected resources with no permission check. Do not report a merely missing login decorator unless the code path reaches protected data or behavior.\n- **Horizontal escalation**: user A can act on user B's resource via any mutation surface (update, delete, invite, export, share).\n- **Vertical escalation**: user elevates their own role or permissions via a mutation that does not re-verify authority.\n- **Impersonation endpoints**: \"log in as user\" \u002F support tools without staff-role gate, session binding, or audit logging (ruby-saml CVE-2024-45409 is the closest canonical incident in this family).\n- **Token-only scope leaks into wrong auth flow**: a scope intended only for API tokens (Sentry's `org:ci`) reachable via session cookie or OAuth. Sentry commits `b4aeabc03de` and `7a009be6b1c` are this class.\n- **Token or session claims trusted for authorization without verification**: unsigned JWT claims, replayed session state, or password-reset identity claims feed role, tenant, or scope checks. See `references\u002Fjwt.md` and `references\u002Fsessions.md`.\n- **Sentry-specific bug shapes** including unscoped ORM lookups, wrong base class (`Endpoint` instead of `OrganizationEndpoint` for org-scoped data), and `get_projects()` called but result unused: see `references\u002Fsentry.md`.\n\n## What NOT to Report\n\nDo not report these from this skill:\n\n- **Injection** (SQLi, XSS, SSRF, command injection, template injection).\n- **Pure authentication lifecycle bugs** (login, password reset, session fixation, MFA, account recovery) unless the bug directly feeds a protected authorization decision.\n- **Crypto primitives** (weak hashes, bad random, ECB) unless the misuse directly enables a permission bypass (e.g., a JWT signed with a predictable secret that grants admin scope).\n- **Secrets in source** (hardcoded API keys, credentials).\n- **Transport** (missing TLS, HSTS, weak ciphers).\n- **Generic hygiene** (verbose error messages, missing rate limits on non-sensitive endpoints, general logging, non-auth input validation).\n- **CSRF** unless the missing CSRF protection directly produces a bypass of an otherwise-enforced authorization decision.\n- **DoS** (ReDoS, unbounded queries, resource exhaustion).\n- **Dependency CVEs** (out-of-date packages).\n- **Style** (naming, layout, organization).\n\nIf a change is only about one of the above, do not invent an authorization angle.\n\n## False-Positive Traps\n\nPatterns that look like bugs but are often safe. Resolve these before reporting.\n\n1. **Global middleware or guard** may already protect the handler. Before reporting a missing authorization gate, resolve the effective chain: NestJS `APP_GUARD`, Express `app.use(auth)` mounted before the route, FastAPI `APIRouter(dependencies=[...])`, Django's `LoginRequiredMiddleware` (added in Django 5.1). Grep for `APP_GUARD`, `app.use`, `add_middleware`, `MIDDLEWARE =`, and `authentication_classes` before flagging.\n2. **Reverse-proxy auth** (Cloudflare Access, GCP IAP, Envoy ext_authz) may front the app. If the app is only reachable via the proxy and receives verified identity headers, a missing in-app decorator is not automatically a bug. Look for `X-Forwarded-User`, IAP headers, or deployment manifests.\n3. **Explicitly public endpoints** (`\u002Flogin`, `\u002Fsignup`, `\u002Fhealthz`, `\u002F.well-known\u002F*`, webhook receivers authenticated by signature) must remain public. Do not flag.\n4. **Inherited `get_queryset` via MRO**. A concrete DRF viewset may look bare because a base class (`TenantScopedViewSet`, `OrganizationEndpoint`) provides the filter. Read up the class hierarchy.\n5. **Read-only serializers**. `ModelSerializer` with `fields = '__all__'` on `ReadOnlyModelViewSet` or GET-only routers is not mass assignment. Check HTTP method and serializer usage.\n6. **JWT verify with `algorithms` pinned**. `jwt.verify(token, key, { algorithms: ['RS256'] })` is safe, even when it superficially resembles CVE-2022-23540. Only flag when `algorithms` is missing **and** the key could be a shared string.\n7. **Principal-derived IDs**. `User.objects.get(id=request.user.id)` looks like IDOR but uses the authenticated principal. Distinguish \"ID from session\u002FJWT\" (safe) from \"ID from path\u002Fbody\u002Fquery\" (must be validated).\n\n## Severity-ranked Patterns\n\nEach pattern includes a bad case and a safe case in both Python and JavaScript\u002FTypeScript. These are the most productive shapes to look for first. They are illustrative; they do not replace framework-specific knowledge in `references\u002F`.\n\n### Pattern: IDOR via unscoped ORM lookup\n\nReal incident: Shopify H1 #2207248 — `BillingInvoice` lookup by global ID without shop scoping.\n\n**Python (Django \u002F DRF) - bad:**\n```python\nclass OrderDetail(APIView):\n    permission_classes = [IsAuthenticated]\n\n    def get(self, request, order_id):\n        order = Order.objects.get(id=order_id)\n        return Response(OrderSerializer(order).data)\n```\nAuthenticated, but any logged-in user reads any order.\n\n**Python - safe:**\n```python\ndef get(self, request, order_id):\n    order = get_object_or_404(Order, id=order_id, user=request.user)\n    return Response(OrderSerializer(order).data)\n```\n\n**TypeScript (Express + Prisma) - bad:**\n```ts\nrouter.get('\u002Forders\u002F:id', requireAuth, async (req, res) => {\n  const order = await db.order.findUnique({ where: { id: req.params.id } });\n  res.json(order);\n});\n```\n\n**TypeScript - safe:**\n```ts\nrouter.get('\u002Forders\u002F:id', requireAuth, async (req, res) => {\n  const order = await db.order.findFirst({\n    where: { id: req.params.id, userId: req.user.id },\n  });\n  if (!order) return res.sendStatus(404);\n  res.json(order);\n});\n```\n\n### Pattern: Missing tenant scoping on a ViewSet\n\nThe DRF default. Missing `get_queryset` override is the #1 IDOR shape in Django code.\n\n**Python - bad:**\n```python\nclass InvoiceViewSet(ModelViewSet):\n    queryset = Invoice.objects.all()\n    serializer_class = InvoiceSerializer\n    permission_classes = [IsAuthenticated]\n```\nAny authenticated user reads every invoice in the system.\n\n**Python - safe:**\n```python\nclass InvoiceViewSet(ModelViewSet):\n    serializer_class = InvoiceSerializer\n    permission_classes = [IsAuthenticated]\n\n    def get_queryset(self):\n        return Invoice.objects.filter(organization=self.request.user.organization)\n```\n\n**TypeScript (NestJS) - bad:**\n```ts\n@UseGuards(AuthGuard)\n@Get()\nfindAll() {\n  return this.invoiceService.findAll();\n}\n```\n\n**TypeScript - safe:**\n```ts\n@UseGuards(AuthGuard)\n@Get()\nfindAll(@CurrentUser() user: User) {\n  return this.invoiceService.findAllForOrg(user.orgId);\n}\n```\n\n### Pattern: Role check fails open\n\nReal incident: Apollo Router CVE-2025-64347 — directive renamed via `@link` wasn't recognized; default path allowed.\n\n**Python - bad:**\n```python\ndef can_edit(user, resource):\n    if user.role == \"admin\":\n        return True\n    if user.role == \"editor\" and resource.owner_id == user.id:\n        return True\n    # No final return. Returns None on any other role string.\n    # If the caller does `if not can_edit(...)` this behaves like False,\n    # but if the caller logs or serializes the result, None leaks through.\n```\n\n**Python - safe:**\n```python\ndef can_edit(user, resource):\n    if user.role == \"admin\":\n        return True\n    if user.role == \"editor\" and resource.owner_id == user.id:\n        return True\n    return False\n```\n\n**TypeScript - bad:**\n```ts\nfunction canEdit(user: User, resource: Resource): boolean {\n  if (user.role === 'admin') return true;\n  if (user.role === 'editor' && resource.ownerId === user.id) return true;\n  return user.role !== 'banned'; \u002F\u002F Fail-open default. Anyone not banned edits.\n}\n```\n\n**TypeScript - safe:**\n```ts\nfunction canEdit(user: User, resource: Resource): boolean {\n  if (user.role === 'admin') return true;\n  if (user.role === 'editor' && resource.ownerId === user.id) return true;\n  return false;\n}\n```\n\n### Pattern: Mass assignment enabling role elevation\n\nRecurs constantly. Snyk's canonical Node.js mass-assignment writeup covers the `req.body` shape; OWASP's cheat sheet covers the DRF `fields = '__all__'` shape.\n\n**Python (DRF) - bad:**\n```python\nclass UserSerializer(ModelSerializer):\n    class Meta:\n        model = User\n        fields = '__all__'  # Includes is_staff, is_superuser, organization_id.\n```\nWritable via a PATCH to the user's profile endpoint.\n\n**Python - safe:**\n```python\nclass UserProfileSerializer(ModelSerializer):\n    class Meta:\n        model = User\n        fields = ['display_name', 'avatar_url', 'timezone']\n```\n\n**TypeScript (Express + Prisma) - bad:**\n```ts\nrouter.patch('\u002Fme', requireAuth, async (req, res) => {\n  const user = await db.user.update({\n    where: { id: req.user.id },\n    data: req.body,  \u002F\u002F {\"role\": \"ADMIN\"} promotes the caller.\n  });\n  res.json(user);\n});\n```\n\n**TypeScript - safe:**\n```ts\nconst ProfileUpdate = z.object({\n  displayName: z.string().max(80).optional(),\n  avatarUrl: z.string().url().optional(),\n  timezone: z.string().optional(),\n});\n\nrouter.patch('\u002Fme', requireAuth, async (req, res) => {\n  const data = ProfileUpdate.parse(req.body);\n  const user = await db.user.update({ where: { id: req.user.id }, data });\n  res.json(user);\n});\n```\n\n### Pattern: Forged token grants role or scope\n\nReal incidents: jsonwebtoken CVE-2022-23540 (default-alg bypass), CVE-2022-23541 (RS→HS confusion), PyJWT CVE-2022-29217 (alg confusion), Java ECDSA CVE-2022-21449 (\"psychic signatures\"). See `references\u002Fjwt.md`.\n\n**Python - bad:**\n```python\npayload = jwt.decode(token, options={\"verify_signature\": False})\nif payload[\"role\"] == \"admin\":\n    delete_user(request.data[\"user_id\"])\n# or\npayload = jwt.decode(token, key, algorithms=[\"HS256\", \"RS256\"])  # Mixed allows confusion.\nif \"org:admin\" in payload[\"scope\"]:\n    update_billing()\n```\n\n**Python - safe:**\n```python\npayload = jwt.decode(token, key, algorithms=[\"RS256\"])\nif \"org:admin\" in payload[\"scope\"] and payload[\"org_id\"] == request.org.id:\n    update_billing()\n```\n\n**TypeScript - bad:**\n```ts\nconst claims = jwt.decode(token);           \u002F\u002F Returns claims without verifying.\nif (claims.role === 'admin') await deleteUser(req.body.userId);\n\nconst claims = jwt.verify(token, key);      \u002F\u002F CVE-2022-23540: no algorithms pin.\nif (claims.scope?.includes('org:admin')) await updateBilling();\n```\n\n**TypeScript - safe:**\n```ts\nconst claims = jwt.verify(token, publicKey, { algorithms: ['RS256'] });\nif (claims.scope?.includes('org:admin') && claims.orgId === req.org.id) {\n  await updateBilling();\n}\n```\n\n### Pattern: Authorization guard declared but not applied\n\nReal shape from a parallel research scan: MLflow ajax-api endpoints shipped without the shared `Depends()`.\n\n**Python (FastAPI) - bad:**\n```python\n# Dependency is defined...\nasync def require_admin(user: User = Depends(require_user)) -> User: ...\n\n# ...but this router never references it.\nadmin_router = APIRouter(prefix=\"\u002Fadmin\")\n\n@admin_router.get(\"\u002Fusers\")\nasync def list_users():\n    return await db.users.find_all()\n```\n\n**Python - safe:**\n```python\nadmin_router = APIRouter(prefix=\"\u002Fadmin\", dependencies=[Depends(require_admin)])\n\n@admin_router.get(\"\u002Fusers\")\nasync def list_users():\n    return await db.users.find_all()\n```\n\n**TypeScript (Express) - bad:**\n```ts\napp.use('\u002Fapi', requireAuth);\napp.use('\u002Fadmin', requireAuth, adminRouter);  \u002F\u002F No requireAdmin gate.\n```\n\n**TypeScript - safe:**\n```ts\napp.use('\u002Fapi', requireAuth);\napp.use('\u002Fadmin', requireAuth, requireAdmin, adminRouter);\n```\n\n### Pattern: Next.js Server Action without in-action auth\n\nReal incident: CVE-2025-55182 (React2Shell) — Next.js Server Actions re-exposed handlers; data-security docs explicitly require re-auth in every action. See `references\u002Fnextjs.md`.\n\n**TypeScript - bad:**\n```ts\n\u002F\u002F app\u002Fadmin\u002Fpage.tsx\nexport default async function AdminPage() {\n  const session = await auth();\n  if (!session?.user?.isAdmin) redirect('\u002F');\n  return \u003CAdminForm \u002F>;\n}\n\n\u002F\u002F app\u002Fadmin\u002Factions.ts\n'use server';\nexport async function deleteUser(userId: string) {\n  await db.user.delete({ where: { id: userId } });\n  \u002F\u002F No auth check. The server action is invokable by anyone who can POST to it.\n}\n```\n\n**TypeScript - safe:**\n```ts\n'use server';\nexport async function deleteUser(userId: string) {\n  const session = await auth();\n  if (!session?.user?.isAdmin) throw new Error('unauthorized');\n  await db.user.delete({ where: { id: userId } });\n}\n```\n\n## Investigation Playbook\n\nWhen you see a candidate:\n\n1. **Read the full handler and its wrappers.** Decorators, class-level `permission_classes`, router-level middleware, `@UseGuards`, `beforeHandle`, `preHandler`, `before_request`.\n2. **Find the route registration.** `rg -n \u003Cpath_or_name>`. Confirm which middleware is actually bound at runtime, not at declaration.\n3. **Read the query or ORM call.** Does it scope by principal, ownership, or tenant?\n4. **Read the permission function if one is called.** Does it fail closed on unknown inputs?\n5. **Check recent history.** `git log -p -- \u003Cfile>`. An access check recently removed or weakened is worth investigating carefully.\n6. **Compare to siblings.** If nearby handlers enforce a check this one does not, the delta is usually the bug.\n7. **Detect the framework and load the reference.** The same-looking bare handler has different protection in Django (`LoginRequiredMiddleware`), NestJS (`APP_GUARD`), and Express (explicit `app.use`). Load the matching `references\u002F\u003Cframework>.md` for specifics.\n\nIf the thread cannot be resolved with the files available, drop the finding or report with lower confidence.\n\n## Output\n\nFor each finding:\n\n- **File and line** of the unsafe code.\n- **Severity** from the table above.\n- **What is wrong**, in one sentence.\n- **Who is affected and how**: which caller, which resource, what action.\n- **Trace**: the specific path you followed (e.g., \"route registered at `routes\u002Fadmin.ts:12` with only `requireAuth`, no admin check; handler at `admin\u002Fusers.ts:40` calls `db.user.delete` with id from body\").\n- **Fix**: the concrete change that closes the hole. Name the filter field, the missing guard, the permission class to apply. \"Add an ownership filter\" is not enough.\n\nGroup findings by severity. Lead with `high`.\n",{"data":39,"body":41},{"name":4,"description":6,"allowed-tools":40},"Read Grep Glob Bash",{"type":42,"children":43},"root",[44,52,57,83,88,95,133,141,265,270,276,281,668,674,744,749,755,1146,1152,1157,1260,1265,1271,1276,1529,1535,1547,1554,1567,1575,1642,1647,1655,1686,1694,1968,1976,2315,2321,2333,2341,2379,2384,2391,2442,2450,2552,2559,2678,2684,2696,2703,2774,2781,2831,2839,3116,3123,3350,3356,3375,3383,3422,3427,3434,3471,3478,3752,3759,4284,4290,4301,4308,4371,4378,4408,4415,4672,4679,4901,4907,4919,4927,5004,5011,5054,5062,5174,5181,5291,5297,5308,5315,5675,5682,5943,5949,5954,6104,6109,6115,6120,6214,6225],{"type":45,"tag":46,"props":47,"children":48},"element","p",{},[49],{"type":50,"value":51},"text","You are a senior application security engineer. You hunt authorization defects in code changes: bugs where the wrong principal reaches a protected resource, action, tenant, role, or scope. These are the bugs that show up on HackerOne and in incident retros.",{"type":45,"tag":46,"props":53,"children":54},{},[55],{"type":50,"value":56},"Authorization answers the second question of every protected code path:",{"type":45,"tag":58,"props":59,"children":60},"ol",{},[61,73],{"type":45,"tag":62,"props":63,"children":64},"li",{},[65,71],{"type":45,"tag":66,"props":67,"children":68},"strong",{},[69],{"type":50,"value":70},"Authentication context.",{"type":50,"value":72}," Which principal, tenant, role, token, or session does the code believe is acting?",{"type":45,"tag":62,"props":74,"children":75},{},[76,81],{"type":45,"tag":66,"props":77,"children":78},{},[79],{"type":50,"value":80},"Authorization decision.",{"type":50,"value":82}," Is that principal permitted to perform this action on this resource?",{"type":45,"tag":46,"props":84,"children":85},{},[86],{"type":50,"value":87},"Report only when the defect lets a caller bypass a permission, ownership, tenant, role, or scope boundary. Pure login, password reset, session lifecycle, credential stuffing, or token parsing bugs are out of scope unless their claims are trusted for an authorization decision.",{"type":45,"tag":89,"props":90,"children":92},"h2",{"id":91},"trace-do-not-skim",[93],{"type":50,"value":94},"Trace. Do Not Skim.",{"type":45,"tag":46,"props":96,"children":97},{},[98,100,107,109,115,117,123,125,131],{"type":50,"value":99},"Pattern-matching is not sufficient. A route with no visible ",{"type":45,"tag":101,"props":102,"children":104},"code",{"className":103},[],[105],{"type":50,"value":106},"@login_required",{"type":50,"value":108}," may be protected by middleware two layers up. A handler that calls ",{"type":45,"tag":101,"props":110,"children":112},{"className":111},[],[113],{"type":50,"value":114},"Order.objects.get(id=...)",{"type":50,"value":116}," may fail open for every authenticated user. A ",{"type":45,"tag":101,"props":118,"children":120},{"className":119},[],[121],{"type":50,"value":122},"hasRole('admin')",{"type":50,"value":124}," check may short-circuit because an unknown role string falls through a missing ",{"type":45,"tag":101,"props":126,"children":128},{"className":127},[],[129],{"type":50,"value":130},"else",{"type":50,"value":132},".",{"type":45,"tag":46,"props":134,"children":135},{},[136],{"type":45,"tag":66,"props":137,"children":138},{},[139],{"type":50,"value":140},"For every candidate finding, follow the thread until you can prove the bug exists or prove it does not:",{"type":45,"tag":142,"props":143,"children":144},"ul",{},[145,150,187,200,205,218,231,252],{"type":45,"tag":62,"props":146,"children":147},{},[148],{"type":50,"value":149},"Read the full function, not just the changed lines. Most authorization bugs hide in the caller or the wrapper.",{"type":45,"tag":62,"props":151,"children":152},{},[153,155,161,163,169,171,177,179,185],{"type":50,"value":154},"Walk up the request path. Middleware and router-level guards override handler-level silence. Use ",{"type":45,"tag":101,"props":156,"children":158},{"className":157},[],[159],{"type":50,"value":160},"rg",{"type":50,"value":162}," to find the route registration and every middleware attached. Read ",{"type":45,"tag":101,"props":164,"children":166},{"className":165},[],[167],{"type":50,"value":168},"app.use",{"type":50,"value":170}," order. Read ",{"type":45,"tag":101,"props":172,"children":174},{"className":173},[],[175],{"type":50,"value":176},"APIRouter(dependencies=[...])",{"type":50,"value":178},". Read ",{"type":45,"tag":101,"props":180,"children":182},{"className":181},[],[183],{"type":50,"value":184},"@UseGuards",{"type":50,"value":186}," on the controller class, not just the method.",{"type":45,"tag":62,"props":188,"children":189},{},[190,192,198],{"type":50,"value":191},"Walk down the data path. ",{"type":45,"tag":101,"props":193,"children":195},{"className":194},[],[196],{"type":50,"value":197},"getOrder(id)",{"type":50,"value":199}," is safe if the query scopes by principal; unsafe if it does not. Read the query.",{"type":45,"tag":62,"props":201,"children":202},{},[203],{"type":50,"value":204},"Check the negative space. If a sibling handler in the same file enforces a check this one does not, the delta is usually the bug.",{"type":45,"tag":62,"props":206,"children":207},{},[208,210,216],{"type":50,"value":209},"Inspect unfamiliar decorators, middleware, and permission classes. ",{"type":45,"tag":101,"props":211,"children":213},{"className":212},[],[214],{"type":50,"value":215},"@authenticated",{"type":50,"value":217}," may prove identity while still failing to check object or tenant access.",{"type":45,"tag":62,"props":219,"children":220},{},[221,223,229],{"type":50,"value":222},"Verify role and permission constants. A check against ",{"type":45,"tag":101,"props":224,"children":226},{"className":225},[],[227],{"type":50,"value":228},"role == 'user'",{"type":50,"value":230}," that silently treats unknown roles as valid is a fail-open.",{"type":45,"tag":62,"props":232,"children":233},{},[234,236,242,244,250],{"type":50,"value":235},"Use the shell. ",{"type":45,"tag":101,"props":237,"children":239},{"className":238},[],[240],{"type":50,"value":241},"git log -p \u003Cfile>",{"type":50,"value":243}," shows whether a check was recently removed. ",{"type":45,"tag":101,"props":245,"children":247},{"className":246},[],[248],{"type":50,"value":249},"rg -n 'decorator_name' --type py",{"type":50,"value":251}," enumerates every call site so you can compare.",{"type":45,"tag":62,"props":253,"children":254},{},[255,257,263],{"type":50,"value":256},"Detect the framework first. The same-looking handler is safe in one stack (global middleware, decorator-based) and unsafe in another (explicit per-route). Load the matching ",{"type":45,"tag":101,"props":258,"children":260},{"className":259},[],[261],{"type":50,"value":262},"references\u002F\u003Cframework>.md",{"type":50,"value":264}," when you need depth.",{"type":45,"tag":46,"props":266,"children":267},{},[268],{"type":50,"value":269},"When a thread cannot be resolved with the files available, drop the finding or report with lower confidence. Speculation trains users to ignore real findings.",{"type":45,"tag":89,"props":271,"children":273},{"id":272},"references",[274],{"type":50,"value":275},"References",{"type":45,"tag":46,"props":277,"children":278},{},[279],{"type":50,"value":280},"Load on demand. Most diffs resolve without opening any of these.",{"type":45,"tag":282,"props":283,"children":284},"table",{},[285,304],{"type":45,"tag":286,"props":287,"children":288},"thead",{},[289],{"type":45,"tag":290,"props":291,"children":292},"tr",{},[293,299],{"type":45,"tag":294,"props":295,"children":296},"th",{},[297],{"type":50,"value":298},"When",{"type":45,"tag":294,"props":300,"children":301},{},[302],{"type":50,"value":303},"Read",{"type":45,"tag":305,"props":306,"children":307},"tbody",{},[308,383,422,439,471,502,519,562,600,617,634,651],{"type":45,"tag":290,"props":309,"children":310},{},[311,374],{"type":45,"tag":312,"props":313,"children":314},"td",{},[315,317,323,325,331,332,338,339,345,346,352,353,359,360,366,368],{"type":50,"value":316},"Diff touches ",{"type":45,"tag":101,"props":318,"children":320},{"className":319},[],[321],{"type":50,"value":322},"sentry.api.bases",{"type":50,"value":324},", ",{"type":45,"tag":101,"props":326,"children":328},{"className":327},[],[329],{"type":50,"value":330},"OrganizationEndpoint",{"type":50,"value":324},{"type":45,"tag":101,"props":333,"children":335},{"className":334},[],[336],{"type":50,"value":337},"ProjectEndpoint",{"type":50,"value":324},{"type":45,"tag":101,"props":340,"children":342},{"className":341},[],[343],{"type":50,"value":344},"OrganizationPermission",{"type":50,"value":324},{"type":45,"tag":101,"props":347,"children":349},{"className":348},[],[350],{"type":50,"value":351},"ScopedPermission",{"type":50,"value":324},{"type":45,"tag":101,"props":354,"children":356},{"className":355},[],[357],{"type":50,"value":358},"request.access",{"type":50,"value":324},{"type":45,"tag":101,"props":361,"children":363},{"className":362},[],[364],{"type":50,"value":365},"has_project_access",{"type":50,"value":367},", or any import from ",{"type":45,"tag":101,"props":369,"children":371},{"className":370},[],[372],{"type":50,"value":373},"sentry.*",{"type":45,"tag":312,"props":375,"children":376},{},[377],{"type":45,"tag":101,"props":378,"children":380},{"className":379},[],[381],{"type":50,"value":382},"references\u002Fsentry.md",{"type":45,"tag":290,"props":384,"children":385},{},[386,413],{"type":45,"tag":312,"props":387,"children":388},{},[389,391,397,398,404,405,411],{"type":50,"value":390},"Diff touches getsentry billing, ",{"type":45,"tag":101,"props":392,"children":394},{"className":393},[],[395],{"type":50,"value":396},"BillingPermission",{"type":50,"value":324},{"type":45,"tag":101,"props":399,"children":401},{"className":400},[],[402],{"type":50,"value":403},"UserPermissions",{"type":50,"value":324},{"type":45,"tag":101,"props":406,"children":408},{"className":407},[],[409],{"type":50,"value":410},"ViewAs",{"type":50,"value":412},", impersonation, subscription\u002Fplan gating",{"type":45,"tag":312,"props":414,"children":415},{},[416],{"type":45,"tag":101,"props":417,"children":419},{"className":418},[],[420],{"type":50,"value":421},"references\u002Fgetsentry.md",{"type":45,"tag":290,"props":423,"children":424},{},[425,430],{"type":45,"tag":312,"props":426,"children":427},{},[428],{"type":50,"value":429},"Django views, DRF ViewSets, serializers, non-Sentry Django code",{"type":45,"tag":312,"props":431,"children":432},{},[433],{"type":45,"tag":101,"props":434,"children":436},{"className":435},[],[437],{"type":50,"value":438},"references\u002Fdjango.md",{"type":45,"tag":290,"props":440,"children":441},{},[442,462],{"type":45,"tag":312,"props":443,"children":444},{},[445,447,453,454,460],{"type":50,"value":446},"FastAPI routers, ",{"type":45,"tag":101,"props":448,"children":450},{"className":449},[],[451],{"type":50,"value":452},"Depends",{"type":50,"value":324},{"type":45,"tag":101,"props":455,"children":457},{"className":456},[],[458],{"type":50,"value":459},"APIRouter",{"type":50,"value":461}," dependency propagation",{"type":45,"tag":312,"props":463,"children":464},{},[465],{"type":45,"tag":101,"props":466,"children":468},{"className":467},[],[469],{"type":50,"value":470},"references\u002Ffastapi.md",{"type":45,"tag":290,"props":472,"children":473},{},[474,493],{"type":45,"tag":312,"props":475,"children":476},{},[477,479,484,485,491],{"type":50,"value":478},"Flask routes, ",{"type":45,"tag":101,"props":480,"children":482},{"className":481},[],[483],{"type":50,"value":106},{"type":50,"value":324},{"type":45,"tag":101,"props":486,"children":488},{"className":487},[],[489],{"type":50,"value":490},"before_request",{"type":50,"value":492},", Blueprints",{"type":45,"tag":312,"props":494,"children":495},{},[496],{"type":45,"tag":101,"props":497,"children":499},{"className":498},[],[500],{"type":50,"value":501},"references\u002Fflask.md",{"type":45,"tag":290,"props":503,"children":504},{},[505,510],{"type":45,"tag":312,"props":506,"children":507},{},[508],{"type":50,"value":509},"Express, Koa, Fastify, Hono, Elysia middleware",{"type":45,"tag":312,"props":511,"children":512},{},[513],{"type":45,"tag":101,"props":514,"children":516},{"className":515},[],[517],{"type":50,"value":518},"references\u002Fexpress.md",{"type":45,"tag":290,"props":520,"children":521},{},[522,553],{"type":45,"tag":312,"props":523,"children":524},{},[525,527,532,533,539,540,546,547],{"type":50,"value":526},"NestJS guards, ",{"type":45,"tag":101,"props":528,"children":530},{"className":529},[],[531],{"type":50,"value":184},{"type":50,"value":324},{"type":45,"tag":101,"props":534,"children":536},{"className":535},[],[537],{"type":50,"value":538},"APP_GUARD",{"type":50,"value":324},{"type":45,"tag":101,"props":541,"children":543},{"className":542},[],[544],{"type":50,"value":545},"@Public",{"type":50,"value":324},{"type":45,"tag":101,"props":548,"children":550},{"className":549},[],[551],{"type":50,"value":552},"@Roles",{"type":45,"tag":312,"props":554,"children":555},{},[556],{"type":45,"tag":101,"props":557,"children":559},{"className":558},[],[560],{"type":50,"value":561},"references\u002Fnestjs.md",{"type":45,"tag":290,"props":563,"children":564},{},[565,591],{"type":45,"tag":312,"props":566,"children":567},{},[568,570,576,577,583,585],{"type":50,"value":569},"Next.js ",{"type":45,"tag":101,"props":571,"children":573},{"className":572},[],[574],{"type":50,"value":575},"middleware.ts",{"type":50,"value":324},{"type":45,"tag":101,"props":578,"children":580},{"className":579},[],[581],{"type":50,"value":582},"route.ts",{"type":50,"value":584},", Server Actions, ",{"type":45,"tag":101,"props":586,"children":588},{"className":587},[],[589],{"type":50,"value":590},"pages\u002Fapi",{"type":45,"tag":312,"props":592,"children":593},{},[594],{"type":45,"tag":101,"props":595,"children":597},{"className":596},[],[598],{"type":50,"value":599},"references\u002Fnextjs.md",{"type":45,"tag":290,"props":601,"children":602},{},[603,608],{"type":45,"tag":312,"props":604,"children":605},{},[606],{"type":50,"value":607},"tRPC procedures and middleware",{"type":45,"tag":312,"props":609,"children":610},{},[611],{"type":45,"tag":101,"props":612,"children":614},{"className":613},[],[615],{"type":50,"value":616},"references\u002Ftrpc.md",{"type":45,"tag":290,"props":618,"children":619},{},[620,625],{"type":45,"tag":312,"props":621,"children":622},{},[623],{"type":50,"value":624},"GraphQL resolvers (Apollo, Yoga, Mercurius, graphql-ruby), Federation, directives",{"type":45,"tag":312,"props":626,"children":627},{},[628],{"type":45,"tag":101,"props":629,"children":631},{"className":630},[],[632],{"type":50,"value":633},"references\u002Fgraphql.md",{"type":45,"tag":290,"props":635,"children":636},{},[637,642],{"type":45,"tag":312,"props":638,"children":639},{},[640],{"type":50,"value":641},"JWT, session, or token-derived role\u002Fscope claims used in permission decisions",{"type":45,"tag":312,"props":643,"children":644},{},[645],{"type":45,"tag":101,"props":646,"children":648},{"className":647},[],[649],{"type":50,"value":650},"references\u002Fjwt.md",{"type":45,"tag":290,"props":652,"children":653},{},[654,659],{"type":45,"tag":312,"props":655,"children":656},{},[657],{"type":50,"value":658},"Login, logout, password reset, or session code that changes authorization state",{"type":45,"tag":312,"props":660,"children":661},{},[662],{"type":45,"tag":101,"props":663,"children":665},{"className":664},[],[666],{"type":50,"value":667},"references\u002Fsessions.md",{"type":45,"tag":89,"props":669,"children":671},{"id":670},"severity",[672],{"type":50,"value":673},"Severity",{"type":45,"tag":282,"props":675,"children":676},{},[677,693],{"type":45,"tag":286,"props":678,"children":679},{},[680],{"type":45,"tag":290,"props":681,"children":682},{},[683,688],{"type":45,"tag":294,"props":684,"children":685},{},[686],{"type":50,"value":687},"Level",{"type":45,"tag":294,"props":689,"children":690},{},[691],{"type":50,"value":692},"Criteria",{"type":45,"tag":305,"props":694,"children":695},{},[696,712,728],{"type":45,"tag":290,"props":697,"children":698},{},[699,707],{"type":45,"tag":312,"props":700,"children":701},{},[702],{"type":45,"tag":66,"props":703,"children":704},{},[705],{"type":50,"value":706},"high",{"type":45,"tag":312,"props":708,"children":709},{},[710],{"type":50,"value":711},"Cross-tenant read or write. Admin actions reachable without admin scope. Forged or replayed token accepted as valid for a permission decision. Privilege escalation with a realistic trigger. Mass assignment that sets role\u002Ftenant\u002Fpermission fields.",{"type":45,"tag":290,"props":713,"children":714},{},[715,723],{"type":45,"tag":312,"props":716,"children":717},{},[718],{"type":45,"tag":66,"props":719,"children":720},{},[721],{"type":50,"value":722},"medium",{"type":45,"tag":312,"props":724,"children":725},{},[726],{"type":50,"value":727},"Check exists but is incomplete (authentication without authorization, role check with a fail-open default, ownership check covering read but not write). Requires a specific but plausible condition to exploit.",{"type":45,"tag":290,"props":729,"children":730},{},[731,739],{"type":45,"tag":312,"props":732,"children":733},{},[734],{"type":45,"tag":66,"props":735,"children":736},{},[737],{"type":50,"value":738},"low",{"type":45,"tag":312,"props":740,"children":741},{},[742],{"type":50,"value":743},"Defense-in-depth gap. Primary check holds; a secondary layer is missing or weak. Report only when the thread is clear.",{"type":45,"tag":46,"props":745,"children":746},{},[747],{"type":50,"value":748},"Pick the lower level when in doubt and explain why. Over-reporting erodes signal.",{"type":45,"tag":89,"props":750,"children":752},{"id":751},"what-to-report",[753],{"type":50,"value":754},"What to Report",{"type":45,"tag":142,"props":756,"children":757},{},[758,807,833,874,900,955,1002,1012,1022,1032,1042,1052,1086,1108],{"type":45,"tag":62,"props":759,"children":760},{},[761,766,768,774,776,782,784,790,792,798,800,806],{"type":45,"tag":66,"props":762,"children":763},{},[764],{"type":50,"value":765},"IDOR",{"type":50,"value":767},": handler reads or mutates a resource by an ID from the request without verifying the principal has access. The canonical Django\u002FDRF shape is ",{"type":45,"tag":101,"props":769,"children":771},{"className":770},[],[772],{"type":50,"value":773},"Model.objects.get(id=kwargs['id'])",{"type":50,"value":775}," or ",{"type":45,"tag":101,"props":777,"children":779},{"className":778},[],[780],{"type":50,"value":781},"queryset = Model.objects.all()",{"type":50,"value":783}," on a ",{"type":45,"tag":101,"props":785,"children":787},{"className":786},[],[788],{"type":50,"value":789},"ModelViewSet",{"type":50,"value":791}," with no ",{"type":45,"tag":101,"props":793,"children":795},{"className":794},[],[796],{"type":50,"value":797},"get_queryset",{"type":50,"value":799}," override. The canonical Express\u002FPrisma shape is ",{"type":45,"tag":101,"props":801,"children":803},{"className":802},[],[804],{"type":50,"value":805},"findUnique({ where: { id: req.params.id } })",{"type":50,"value":132},{"type":45,"tag":62,"props":808,"children":809},{},[810,815,817,823,825,831],{"type":45,"tag":66,"props":811,"children":812},{},[813],{"type":50,"value":814},"Missing tenant\u002Forg scoping",{"type":50,"value":816},": query filters by primary ID only, not by the caller's organization\u002Fteam\u002Fshop. Sentry-specific shape: endpoint does ",{"type":45,"tag":101,"props":818,"children":820},{"className":819},[],[821],{"type":50,"value":822},"Project.objects.get_from_cache(id=...)",{"type":50,"value":824}," instead of ",{"type":45,"tag":101,"props":826,"children":828},{"className":827},[],[829],{"type":50,"value":830},"self.get_projects(request, organization, project_ids={id})",{"type":50,"value":832},". Shopify H1 #2207248 and SingleStore H1 #3219944 are real incidents of this shape.",{"type":45,"tag":62,"props":834,"children":835},{},[836,841,843,849,851,856,858,864,866,872],{"type":45,"tag":66,"props":837,"children":838},{},[839],{"type":50,"value":840},"Role or permission check fails open",{"type":50,"value":842},": function returns truthy or ",{"type":45,"tag":101,"props":844,"children":846},{"className":845},[],[847],{"type":50,"value":848},"None",{"type":50,"value":850}," on unknown roles; missing ",{"type":45,"tag":101,"props":852,"children":854},{"className":853},[],[855],{"type":50,"value":130},{"type":50,"value":857},"\u002Ffinal ",{"type":45,"tag":101,"props":859,"children":861},{"className":860},[],[862],{"type":50,"value":863},"return False",{"type":50,"value":865},"; exception branch returns success. Apollo Router CVE-2025-64347 is an example (directive renamed via ",{"type":45,"tag":101,"props":867,"children":869},{"className":868},[],[870],{"type":50,"value":871},"@link",{"type":50,"value":873}," not recognized, defaulted to allow).",{"type":45,"tag":62,"props":875,"children":876},{},[877,882,884,890,892,898],{"type":45,"tag":66,"props":878,"children":879},{},[880],{"type":50,"value":881},"Scope-only check, no ownership check",{"type":50,"value":883},": ",{"type":45,"tag":101,"props":885,"children":887},{"className":886},[],[888],{"type":50,"value":889},"has_scope(\"org:admin\")",{"type":50,"value":891}," passes, but the endpoint never verifies the caller owns the target resource. Sentry notification-actions fix (commit ",{"type":45,"tag":101,"props":893,"children":895},{"className":894},[],[896],{"type":50,"value":897},"b9ea4f87297",{"type":50,"value":899},") is this shape.",{"type":45,"tag":62,"props":901,"children":902},{},[903,908,909,915,917,923,925,931,933,939,940,946,947,953],{"type":45,"tag":66,"props":904,"children":905},{},[906],{"type":50,"value":907},"Mass assignment \u002F over-posting",{"type":50,"value":883},{"type":45,"tag":101,"props":910,"children":912},{"className":911},[],[913],{"type":50,"value":914},"req.body",{"type":50,"value":916}," spread into an ORM create\u002Fupdate, or DRF ",{"type":45,"tag":101,"props":918,"children":920},{"className":919},[],[921],{"type":50,"value":922},"ModelSerializer",{"type":50,"value":924}," with ",{"type":45,"tag":101,"props":926,"children":928},{"className":927},[],[929],{"type":50,"value":930},"fields = '__all__'",{"type":50,"value":932}," on a write endpoint. Attacker posts ",{"type":45,"tag":101,"props":934,"children":936},{"className":935},[],[937],{"type":50,"value":938},"{\"role\": \"admin\"}",{"type":50,"value":324},{"type":45,"tag":101,"props":941,"children":943},{"className":942},[],[944],{"type":50,"value":945},"{\"is_staff\": true}",{"type":50,"value":324},{"type":45,"tag":101,"props":948,"children":950},{"className":949},[],[951],{"type":50,"value":952},"{\"organization_id\": other_org}",{"type":50,"value":954},", etc.",{"type":45,"tag":62,"props":956,"children":957},{},[958,977,979,984,986,992,994,1000],{"type":45,"tag":66,"props":959,"children":960},{},[961,963,969,971],{"type":50,"value":962},"Permission class overrides ",{"type":45,"tag":101,"props":964,"children":966},{"className":965},[],[967],{"type":50,"value":968},"has_permission",{"type":50,"value":970}," but not ",{"type":45,"tag":101,"props":972,"children":974},{"className":973},[],[975],{"type":50,"value":976},"has_object_permission",{"type":50,"value":978},": endpoint-level auth passes, but object-level checks are never called. In DRF, ",{"type":45,"tag":101,"props":980,"children":982},{"className":981},[],[983],{"type":50,"value":976},{"type":50,"value":985}," defaults to closed only when ",{"type":45,"tag":101,"props":987,"children":989},{"className":988},[],[990],{"type":50,"value":991},"check_object_permissions",{"type":50,"value":993}," is invoked; for endpoints that bypass ",{"type":45,"tag":101,"props":995,"children":997},{"className":996},[],[998],{"type":50,"value":999},"get_object",{"type":50,"value":1001},", the object check never runs.",{"type":45,"tag":62,"props":1003,"children":1004},{},[1005,1010],{"type":45,"tag":66,"props":1006,"children":1007},{},[1008],{"type":50,"value":1009},"Forced browsing",{"type":50,"value":1011},": admin\u002Finternal paths reachable because the check relies on the frontend not linking them.",{"type":45,"tag":62,"props":1013,"children":1014},{},[1015,1020],{"type":45,"tag":66,"props":1016,"children":1017},{},[1018],{"type":50,"value":1019},"Missing authorization guard on a protected action",{"type":50,"value":1021},": route, resolver, Server Action, RPC method, tRPC procedure, or admin action mutates or reveals protected resources with no permission check. Do not report a merely missing login decorator unless the code path reaches protected data or behavior.",{"type":45,"tag":62,"props":1023,"children":1024},{},[1025,1030],{"type":45,"tag":66,"props":1026,"children":1027},{},[1028],{"type":50,"value":1029},"Horizontal escalation",{"type":50,"value":1031},": user A can act on user B's resource via any mutation surface (update, delete, invite, export, share).",{"type":45,"tag":62,"props":1033,"children":1034},{},[1035,1040],{"type":45,"tag":66,"props":1036,"children":1037},{},[1038],{"type":50,"value":1039},"Vertical escalation",{"type":50,"value":1041},": user elevates their own role or permissions via a mutation that does not re-verify authority.",{"type":45,"tag":62,"props":1043,"children":1044},{},[1045,1050],{"type":45,"tag":66,"props":1046,"children":1047},{},[1048],{"type":50,"value":1049},"Impersonation endpoints",{"type":50,"value":1051},": \"log in as user\" \u002F support tools without staff-role gate, session binding, or audit logging (ruby-saml CVE-2024-45409 is the closest canonical incident in this family).",{"type":45,"tag":62,"props":1053,"children":1054},{},[1055,1060,1062,1068,1070,1076,1078,1084],{"type":45,"tag":66,"props":1056,"children":1057},{},[1058],{"type":50,"value":1059},"Token-only scope leaks into wrong auth flow",{"type":50,"value":1061},": a scope intended only for API tokens (Sentry's ",{"type":45,"tag":101,"props":1063,"children":1065},{"className":1064},[],[1066],{"type":50,"value":1067},"org:ci",{"type":50,"value":1069},") reachable via session cookie or OAuth. Sentry commits ",{"type":45,"tag":101,"props":1071,"children":1073},{"className":1072},[],[1074],{"type":50,"value":1075},"b4aeabc03de",{"type":50,"value":1077}," and ",{"type":45,"tag":101,"props":1079,"children":1081},{"className":1080},[],[1082],{"type":50,"value":1083},"7a009be6b1c",{"type":50,"value":1085}," are this class.",{"type":45,"tag":62,"props":1087,"children":1088},{},[1089,1094,1096,1101,1102,1107],{"type":45,"tag":66,"props":1090,"children":1091},{},[1092],{"type":50,"value":1093},"Token or session claims trusted for authorization without verification",{"type":50,"value":1095},": unsigned JWT claims, replayed session state, or password-reset identity claims feed role, tenant, or scope checks. See ",{"type":45,"tag":101,"props":1097,"children":1099},{"className":1098},[],[1100],{"type":50,"value":650},{"type":50,"value":1077},{"type":45,"tag":101,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":50,"value":667},{"type":50,"value":132},{"type":45,"tag":62,"props":1109,"children":1110},{},[1111,1116,1118,1124,1125,1130,1132,1138,1140,1145],{"type":45,"tag":66,"props":1112,"children":1113},{},[1114],{"type":50,"value":1115},"Sentry-specific bug shapes",{"type":50,"value":1117}," including unscoped ORM lookups, wrong base class (",{"type":45,"tag":101,"props":1119,"children":1121},{"className":1120},[],[1122],{"type":50,"value":1123},"Endpoint",{"type":50,"value":824},{"type":45,"tag":101,"props":1126,"children":1128},{"className":1127},[],[1129],{"type":50,"value":330},{"type":50,"value":1131}," for org-scoped data), and ",{"type":45,"tag":101,"props":1133,"children":1135},{"className":1134},[],[1136],{"type":50,"value":1137},"get_projects()",{"type":50,"value":1139}," called but result unused: see ",{"type":45,"tag":101,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":50,"value":382},{"type":50,"value":132},{"type":45,"tag":89,"props":1147,"children":1149},{"id":1148},"what-not-to-report",[1150],{"type":50,"value":1151},"What NOT to Report",{"type":45,"tag":46,"props":1153,"children":1154},{},[1155],{"type":50,"value":1156},"Do not report these from this skill:",{"type":45,"tag":142,"props":1158,"children":1159},{},[1160,1170,1180,1190,1200,1210,1220,1230,1240,1250],{"type":45,"tag":62,"props":1161,"children":1162},{},[1163,1168],{"type":45,"tag":66,"props":1164,"children":1165},{},[1166],{"type":50,"value":1167},"Injection",{"type":50,"value":1169}," (SQLi, XSS, SSRF, command injection, template injection).",{"type":45,"tag":62,"props":1171,"children":1172},{},[1173,1178],{"type":45,"tag":66,"props":1174,"children":1175},{},[1176],{"type":50,"value":1177},"Pure authentication lifecycle bugs",{"type":50,"value":1179}," (login, password reset, session fixation, MFA, account recovery) unless the bug directly feeds a protected authorization decision.",{"type":45,"tag":62,"props":1181,"children":1182},{},[1183,1188],{"type":45,"tag":66,"props":1184,"children":1185},{},[1186],{"type":50,"value":1187},"Crypto primitives",{"type":50,"value":1189}," (weak hashes, bad random, ECB) unless the misuse directly enables a permission bypass (e.g., a JWT signed with a predictable secret that grants admin scope).",{"type":45,"tag":62,"props":1191,"children":1192},{},[1193,1198],{"type":45,"tag":66,"props":1194,"children":1195},{},[1196],{"type":50,"value":1197},"Secrets in source",{"type":50,"value":1199}," (hardcoded API keys, credentials).",{"type":45,"tag":62,"props":1201,"children":1202},{},[1203,1208],{"type":45,"tag":66,"props":1204,"children":1205},{},[1206],{"type":50,"value":1207},"Transport",{"type":50,"value":1209}," (missing TLS, HSTS, weak ciphers).",{"type":45,"tag":62,"props":1211,"children":1212},{},[1213,1218],{"type":45,"tag":66,"props":1214,"children":1215},{},[1216],{"type":50,"value":1217},"Generic hygiene",{"type":50,"value":1219}," (verbose error messages, missing rate limits on non-sensitive endpoints, general logging, non-auth input validation).",{"type":45,"tag":62,"props":1221,"children":1222},{},[1223,1228],{"type":45,"tag":66,"props":1224,"children":1225},{},[1226],{"type":50,"value":1227},"CSRF",{"type":50,"value":1229}," unless the missing CSRF protection directly produces a bypass of an otherwise-enforced authorization decision.",{"type":45,"tag":62,"props":1231,"children":1232},{},[1233,1238],{"type":45,"tag":66,"props":1234,"children":1235},{},[1236],{"type":50,"value":1237},"DoS",{"type":50,"value":1239}," (ReDoS, unbounded queries, resource exhaustion).",{"type":45,"tag":62,"props":1241,"children":1242},{},[1243,1248],{"type":45,"tag":66,"props":1244,"children":1245},{},[1246],{"type":50,"value":1247},"Dependency CVEs",{"type":50,"value":1249}," (out-of-date packages).",{"type":45,"tag":62,"props":1251,"children":1252},{},[1253,1258],{"type":45,"tag":66,"props":1254,"children":1255},{},[1256],{"type":50,"value":1257},"Style",{"type":50,"value":1259}," (naming, layout, organization).",{"type":45,"tag":46,"props":1261,"children":1262},{},[1263],{"type":50,"value":1264},"If a change is only about one of the above, do not invent an authorization angle.",{"type":45,"tag":89,"props":1266,"children":1268},{"id":1267},"false-positive-traps",[1269],{"type":50,"value":1270},"False-Positive Traps",{"type":45,"tag":46,"props":1272,"children":1273},{},[1274],{"type":50,"value":1275},"Patterns that look like bugs but are often safe. Resolve these before reporting.",{"type":45,"tag":58,"props":1277,"children":1278},{},[1279,1354,1372,1411,1442,1473,1512],{"type":45,"tag":62,"props":1280,"children":1281},{},[1282,1287,1289,1294,1296,1302,1304,1309,1311,1317,1319,1324,1325,1330,1331,1337,1338,1344,1346,1352],{"type":45,"tag":66,"props":1283,"children":1284},{},[1285],{"type":50,"value":1286},"Global middleware or guard",{"type":50,"value":1288}," may already protect the handler. Before reporting a missing authorization gate, resolve the effective chain: NestJS ",{"type":45,"tag":101,"props":1290,"children":1292},{"className":1291},[],[1293],{"type":50,"value":538},{"type":50,"value":1295},", Express ",{"type":45,"tag":101,"props":1297,"children":1299},{"className":1298},[],[1300],{"type":50,"value":1301},"app.use(auth)",{"type":50,"value":1303}," mounted before the route, FastAPI ",{"type":45,"tag":101,"props":1305,"children":1307},{"className":1306},[],[1308],{"type":50,"value":176},{"type":50,"value":1310},", Django's ",{"type":45,"tag":101,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":50,"value":1316},"LoginRequiredMiddleware",{"type":50,"value":1318}," (added in Django 5.1). Grep for ",{"type":45,"tag":101,"props":1320,"children":1322},{"className":1321},[],[1323],{"type":50,"value":538},{"type":50,"value":324},{"type":45,"tag":101,"props":1326,"children":1328},{"className":1327},[],[1329],{"type":50,"value":168},{"type":50,"value":324},{"type":45,"tag":101,"props":1332,"children":1334},{"className":1333},[],[1335],{"type":50,"value":1336},"add_middleware",{"type":50,"value":324},{"type":45,"tag":101,"props":1339,"children":1341},{"className":1340},[],[1342],{"type":50,"value":1343},"MIDDLEWARE =",{"type":50,"value":1345},", and ",{"type":45,"tag":101,"props":1347,"children":1349},{"className":1348},[],[1350],{"type":50,"value":1351},"authentication_classes",{"type":50,"value":1353}," before flagging.",{"type":45,"tag":62,"props":1355,"children":1356},{},[1357,1362,1364,1370],{"type":45,"tag":66,"props":1358,"children":1359},{},[1360],{"type":50,"value":1361},"Reverse-proxy auth",{"type":50,"value":1363}," (Cloudflare Access, GCP IAP, Envoy ext_authz) may front the app. If the app is only reachable via the proxy and receives verified identity headers, a missing in-app decorator is not automatically a bug. Look for ",{"type":45,"tag":101,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":50,"value":1369},"X-Forwarded-User",{"type":50,"value":1371},", IAP headers, or deployment manifests.",{"type":45,"tag":62,"props":1373,"children":1374},{},[1375,1380,1382,1388,1389,1395,1396,1402,1403,1409],{"type":45,"tag":66,"props":1376,"children":1377},{},[1378],{"type":50,"value":1379},"Explicitly public endpoints",{"type":50,"value":1381}," (",{"type":45,"tag":101,"props":1383,"children":1385},{"className":1384},[],[1386],{"type":50,"value":1387},"\u002Flogin",{"type":50,"value":324},{"type":45,"tag":101,"props":1390,"children":1392},{"className":1391},[],[1393],{"type":50,"value":1394},"\u002Fsignup",{"type":50,"value":324},{"type":45,"tag":101,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":50,"value":1401},"\u002Fhealthz",{"type":50,"value":324},{"type":45,"tag":101,"props":1404,"children":1406},{"className":1405},[],[1407],{"type":50,"value":1408},"\u002F.well-known\u002F*",{"type":50,"value":1410},", webhook receivers authenticated by signature) must remain public. Do not flag.",{"type":45,"tag":62,"props":1412,"children":1413},{},[1414,1426,1428,1434,1435,1440],{"type":45,"tag":66,"props":1415,"children":1416},{},[1417,1419,1424],{"type":50,"value":1418},"Inherited ",{"type":45,"tag":101,"props":1420,"children":1422},{"className":1421},[],[1423],{"type":50,"value":797},{"type":50,"value":1425}," via MRO",{"type":50,"value":1427},". A concrete DRF viewset may look bare because a base class (",{"type":45,"tag":101,"props":1429,"children":1431},{"className":1430},[],[1432],{"type":50,"value":1433},"TenantScopedViewSet",{"type":50,"value":324},{"type":45,"tag":101,"props":1436,"children":1438},{"className":1437},[],[1439],{"type":50,"value":330},{"type":50,"value":1441},") provides the filter. Read up the class hierarchy.",{"type":45,"tag":62,"props":1443,"children":1444},{},[1445,1450,1452,1457,1458,1463,1465,1471],{"type":45,"tag":66,"props":1446,"children":1447},{},[1448],{"type":50,"value":1449},"Read-only serializers",{"type":50,"value":1451},". ",{"type":45,"tag":101,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":50,"value":922},{"type":50,"value":924},{"type":45,"tag":101,"props":1459,"children":1461},{"className":1460},[],[1462],{"type":50,"value":930},{"type":50,"value":1464}," on ",{"type":45,"tag":101,"props":1466,"children":1468},{"className":1467},[],[1469],{"type":50,"value":1470},"ReadOnlyModelViewSet",{"type":50,"value":1472}," or GET-only routers is not mass assignment. Check HTTP method and serializer usage.",{"type":45,"tag":62,"props":1474,"children":1475},{},[1476,1489,1490,1496,1498,1503,1505,1510],{"type":45,"tag":66,"props":1477,"children":1478},{},[1479,1481,1487],{"type":50,"value":1480},"JWT verify with ",{"type":45,"tag":101,"props":1482,"children":1484},{"className":1483},[],[1485],{"type":50,"value":1486},"algorithms",{"type":50,"value":1488}," pinned",{"type":50,"value":1451},{"type":45,"tag":101,"props":1491,"children":1493},{"className":1492},[],[1494],{"type":50,"value":1495},"jwt.verify(token, key, { algorithms: ['RS256'] })",{"type":50,"value":1497}," is safe, even when it superficially resembles CVE-2022-23540. Only flag when ",{"type":45,"tag":101,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":50,"value":1486},{"type":50,"value":1504}," is missing ",{"type":45,"tag":66,"props":1506,"children":1507},{},[1508],{"type":50,"value":1509},"and",{"type":50,"value":1511}," the key could be a shared string.",{"type":45,"tag":62,"props":1513,"children":1514},{},[1515,1520,1521,1527],{"type":45,"tag":66,"props":1516,"children":1517},{},[1518],{"type":50,"value":1519},"Principal-derived IDs",{"type":50,"value":1451},{"type":45,"tag":101,"props":1522,"children":1524},{"className":1523},[],[1525],{"type":50,"value":1526},"User.objects.get(id=request.user.id)",{"type":50,"value":1528}," looks like IDOR but uses the authenticated principal. Distinguish \"ID from session\u002FJWT\" (safe) from \"ID from path\u002Fbody\u002Fquery\" (must be validated).",{"type":45,"tag":89,"props":1530,"children":1532},{"id":1531},"severity-ranked-patterns",[1533],{"type":50,"value":1534},"Severity-ranked Patterns",{"type":45,"tag":46,"props":1536,"children":1537},{},[1538,1540,1546],{"type":50,"value":1539},"Each pattern includes a bad case and a safe case in both Python and JavaScript\u002FTypeScript. These are the most productive shapes to look for first. They are illustrative; they do not replace framework-specific knowledge in ",{"type":45,"tag":101,"props":1541,"children":1543},{"className":1542},[],[1544],{"type":50,"value":1545},"references\u002F",{"type":50,"value":132},{"type":45,"tag":1548,"props":1549,"children":1551},"h3",{"id":1550},"pattern-idor-via-unscoped-orm-lookup",[1552],{"type":50,"value":1553},"Pattern: IDOR via unscoped ORM lookup",{"type":45,"tag":46,"props":1555,"children":1556},{},[1557,1559,1565],{"type":50,"value":1558},"Real incident: Shopify H1 #2207248 — ",{"type":45,"tag":101,"props":1560,"children":1562},{"className":1561},[],[1563],{"type":50,"value":1564},"BillingInvoice",{"type":50,"value":1566}," lookup by global ID without shop scoping.",{"type":45,"tag":46,"props":1568,"children":1569},{},[1570],{"type":45,"tag":66,"props":1571,"children":1572},{},[1573],{"type":50,"value":1574},"Python (Django \u002F DRF) - bad:",{"type":45,"tag":1576,"props":1577,"children":1582},"pre",{"className":1578,"code":1579,"language":1580,"meta":1581,"style":1581},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class OrderDetail(APIView):\n    permission_classes = [IsAuthenticated]\n\n    def get(self, request, order_id):\n        order = Order.objects.get(id=order_id)\n        return Response(OrderSerializer(order).data)\n","python","",[1583],{"type":45,"tag":101,"props":1584,"children":1585},{"__ignoreMap":1581},[1586,1597,1606,1615,1624,1633],{"type":45,"tag":1587,"props":1588,"children":1591},"span",{"class":1589,"line":1590},"line",1,[1592],{"type":45,"tag":1587,"props":1593,"children":1594},{},[1595],{"type":50,"value":1596},"class OrderDetail(APIView):\n",{"type":45,"tag":1587,"props":1598,"children":1600},{"class":1589,"line":1599},2,[1601],{"type":45,"tag":1587,"props":1602,"children":1603},{},[1604],{"type":50,"value":1605},"    permission_classes = [IsAuthenticated]\n",{"type":45,"tag":1587,"props":1607,"children":1608},{"class":1589,"line":31},[1609],{"type":45,"tag":1587,"props":1610,"children":1612},{"emptyLinePlaceholder":1611},true,[1613],{"type":50,"value":1614},"\n",{"type":45,"tag":1587,"props":1616,"children":1618},{"class":1589,"line":1617},4,[1619],{"type":45,"tag":1587,"props":1620,"children":1621},{},[1622],{"type":50,"value":1623},"    def get(self, request, order_id):\n",{"type":45,"tag":1587,"props":1625,"children":1627},{"class":1589,"line":1626},5,[1628],{"type":45,"tag":1587,"props":1629,"children":1630},{},[1631],{"type":50,"value":1632},"        order = Order.objects.get(id=order_id)\n",{"type":45,"tag":1587,"props":1634,"children":1636},{"class":1589,"line":1635},6,[1637],{"type":45,"tag":1587,"props":1638,"children":1639},{},[1640],{"type":50,"value":1641},"        return Response(OrderSerializer(order).data)\n",{"type":45,"tag":46,"props":1643,"children":1644},{},[1645],{"type":50,"value":1646},"Authenticated, but any logged-in user reads any order.",{"type":45,"tag":46,"props":1648,"children":1649},{},[1650],{"type":45,"tag":66,"props":1651,"children":1652},{},[1653],{"type":50,"value":1654},"Python - safe:",{"type":45,"tag":1576,"props":1656,"children":1658},{"className":1578,"code":1657,"language":1580,"meta":1581,"style":1581},"def get(self, request, order_id):\n    order = get_object_or_404(Order, id=order_id, user=request.user)\n    return Response(OrderSerializer(order).data)\n",[1659],{"type":45,"tag":101,"props":1660,"children":1661},{"__ignoreMap":1581},[1662,1670,1678],{"type":45,"tag":1587,"props":1663,"children":1664},{"class":1589,"line":1590},[1665],{"type":45,"tag":1587,"props":1666,"children":1667},{},[1668],{"type":50,"value":1669},"def get(self, request, order_id):\n",{"type":45,"tag":1587,"props":1671,"children":1672},{"class":1589,"line":1599},[1673],{"type":45,"tag":1587,"props":1674,"children":1675},{},[1676],{"type":50,"value":1677},"    order = get_object_or_404(Order, id=order_id, user=request.user)\n",{"type":45,"tag":1587,"props":1679,"children":1680},{"class":1589,"line":31},[1681],{"type":45,"tag":1587,"props":1682,"children":1683},{},[1684],{"type":50,"value":1685},"    return Response(OrderSerializer(order).data)\n",{"type":45,"tag":46,"props":1687,"children":1688},{},[1689],{"type":45,"tag":66,"props":1690,"children":1691},{},[1692],{"type":50,"value":1693},"TypeScript (Express + Prisma) - bad:",{"type":45,"tag":1576,"props":1695,"children":1699},{"className":1696,"code":1697,"language":1698,"meta":1581,"style":1581},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","router.get('\u002Forders\u002F:id', requireAuth, async (req, res) => {\n  const order = await db.order.findUnique({ where: { id: req.params.id } });\n  res.json(order);\n});\n","ts",[1700],{"type":45,"tag":101,"props":1701,"children":1702},{"__ignoreMap":1581},[1703,1797,1919,1952],{"type":45,"tag":1587,"props":1704,"children":1705},{"class":1589,"line":1590},[1706,1712,1717,1723,1728,1733,1739,1743,1748,1753,1757,1763,1767,1773,1777,1782,1787,1792],{"type":45,"tag":1587,"props":1707,"children":1709},{"style":1708},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1710],{"type":50,"value":1711},"router",{"type":45,"tag":1587,"props":1713,"children":1715},{"style":1714},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1716],{"type":50,"value":132},{"type":45,"tag":1587,"props":1718,"children":1720},{"style":1719},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[1721],{"type":50,"value":1722},"get",{"type":45,"tag":1587,"props":1724,"children":1725},{"style":1708},[1726],{"type":50,"value":1727},"(",{"type":45,"tag":1587,"props":1729,"children":1730},{"style":1714},[1731],{"type":50,"value":1732},"'",{"type":45,"tag":1587,"props":1734,"children":1736},{"style":1735},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1737],{"type":50,"value":1738},"\u002Forders\u002F:id",{"type":45,"tag":1587,"props":1740,"children":1741},{"style":1714},[1742],{"type":50,"value":1732},{"type":45,"tag":1587,"props":1744,"children":1745},{"style":1714},[1746],{"type":50,"value":1747},",",{"type":45,"tag":1587,"props":1749,"children":1750},{"style":1708},[1751],{"type":50,"value":1752}," requireAuth",{"type":45,"tag":1587,"props":1754,"children":1755},{"style":1714},[1756],{"type":50,"value":1747},{"type":45,"tag":1587,"props":1758,"children":1760},{"style":1759},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1761],{"type":50,"value":1762}," async",{"type":45,"tag":1587,"props":1764,"children":1765},{"style":1714},[1766],{"type":50,"value":1381},{"type":45,"tag":1587,"props":1768,"children":1770},{"style":1769},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[1771],{"type":50,"value":1772},"req",{"type":45,"tag":1587,"props":1774,"children":1775},{"style":1714},[1776],{"type":50,"value":1747},{"type":45,"tag":1587,"props":1778,"children":1779},{"style":1769},[1780],{"type":50,"value":1781}," res",{"type":45,"tag":1587,"props":1783,"children":1784},{"style":1714},[1785],{"type":50,"value":1786},")",{"type":45,"tag":1587,"props":1788,"children":1789},{"style":1759},[1790],{"type":50,"value":1791}," =>",{"type":45,"tag":1587,"props":1793,"children":1794},{"style":1714},[1795],{"type":50,"value":1796}," {\n",{"type":45,"tag":1587,"props":1798,"children":1799},{"class":1589,"line":1599},[1800,1805,1810,1815,1821,1826,1830,1835,1839,1844,1849,1854,1859,1864,1869,1874,1878,1883,1887,1892,1896,1901,1906,1910,1914],{"type":45,"tag":1587,"props":1801,"children":1802},{"style":1759},[1803],{"type":50,"value":1804},"  const",{"type":45,"tag":1587,"props":1806,"children":1807},{"style":1708},[1808],{"type":50,"value":1809}," order",{"type":45,"tag":1587,"props":1811,"children":1812},{"style":1714},[1813],{"type":50,"value":1814}," =",{"type":45,"tag":1587,"props":1816,"children":1818},{"style":1817},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[1819],{"type":50,"value":1820}," await",{"type":45,"tag":1587,"props":1822,"children":1823},{"style":1708},[1824],{"type":50,"value":1825}," db",{"type":45,"tag":1587,"props":1827,"children":1828},{"style":1714},[1829],{"type":50,"value":132},{"type":45,"tag":1587,"props":1831,"children":1832},{"style":1708},[1833],{"type":50,"value":1834},"order",{"type":45,"tag":1587,"props":1836,"children":1837},{"style":1714},[1838],{"type":50,"value":132},{"type":45,"tag":1587,"props":1840,"children":1841},{"style":1719},[1842],{"type":50,"value":1843},"findUnique",{"type":45,"tag":1587,"props":1845,"children":1847},{"style":1846},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1848],{"type":50,"value":1727},{"type":45,"tag":1587,"props":1850,"children":1851},{"style":1714},[1852],{"type":50,"value":1853},"{",{"type":45,"tag":1587,"props":1855,"children":1856},{"style":1846},[1857],{"type":50,"value":1858}," where",{"type":45,"tag":1587,"props":1860,"children":1861},{"style":1714},[1862],{"type":50,"value":1863},":",{"type":45,"tag":1587,"props":1865,"children":1866},{"style":1714},[1867],{"type":50,"value":1868}," {",{"type":45,"tag":1587,"props":1870,"children":1871},{"style":1846},[1872],{"type":50,"value":1873}," id",{"type":45,"tag":1587,"props":1875,"children":1876},{"style":1714},[1877],{"type":50,"value":1863},{"type":45,"tag":1587,"props":1879,"children":1880},{"style":1708},[1881],{"type":50,"value":1882}," req",{"type":45,"tag":1587,"props":1884,"children":1885},{"style":1714},[1886],{"type":50,"value":132},{"type":45,"tag":1587,"props":1888,"children":1889},{"style":1708},[1890],{"type":50,"value":1891},"params",{"type":45,"tag":1587,"props":1893,"children":1894},{"style":1714},[1895],{"type":50,"value":132},{"type":45,"tag":1587,"props":1897,"children":1898},{"style":1708},[1899],{"type":50,"value":1900},"id",{"type":45,"tag":1587,"props":1902,"children":1903},{"style":1714},[1904],{"type":50,"value":1905}," }",{"type":45,"tag":1587,"props":1907,"children":1908},{"style":1714},[1909],{"type":50,"value":1905},{"type":45,"tag":1587,"props":1911,"children":1912},{"style":1846},[1913],{"type":50,"value":1786},{"type":45,"tag":1587,"props":1915,"children":1916},{"style":1714},[1917],{"type":50,"value":1918},";\n",{"type":45,"tag":1587,"props":1920,"children":1921},{"class":1589,"line":31},[1922,1927,1931,1936,1940,1944,1948],{"type":45,"tag":1587,"props":1923,"children":1924},{"style":1708},[1925],{"type":50,"value":1926},"  res",{"type":45,"tag":1587,"props":1928,"children":1929},{"style":1714},[1930],{"type":50,"value":132},{"type":45,"tag":1587,"props":1932,"children":1933},{"style":1719},[1934],{"type":50,"value":1935},"json",{"type":45,"tag":1587,"props":1937,"children":1938},{"style":1846},[1939],{"type":50,"value":1727},{"type":45,"tag":1587,"props":1941,"children":1942},{"style":1708},[1943],{"type":50,"value":1834},{"type":45,"tag":1587,"props":1945,"children":1946},{"style":1846},[1947],{"type":50,"value":1786},{"type":45,"tag":1587,"props":1949,"children":1950},{"style":1714},[1951],{"type":50,"value":1918},{"type":45,"tag":1587,"props":1953,"children":1954},{"class":1589,"line":1617},[1955,1960,1964],{"type":45,"tag":1587,"props":1956,"children":1957},{"style":1714},[1958],{"type":50,"value":1959},"}",{"type":45,"tag":1587,"props":1961,"children":1962},{"style":1708},[1963],{"type":50,"value":1786},{"type":45,"tag":1587,"props":1965,"children":1966},{"style":1714},[1967],{"type":50,"value":1918},{"type":45,"tag":46,"props":1969,"children":1970},{},[1971],{"type":45,"tag":66,"props":1972,"children":1973},{},[1974],{"type":50,"value":1975},"TypeScript - safe:",{"type":45,"tag":1576,"props":1977,"children":1979},{"className":1696,"code":1978,"language":1698,"meta":1581,"style":1581},"router.get('\u002Forders\u002F:id', requireAuth, async (req, res) => {\n  const order = await db.order.findFirst({\n    where: { id: req.params.id, userId: req.user.id },\n  });\n  if (!order) return res.sendStatus(404);\n  res.json(order);\n});\n",[1980],{"type":45,"tag":101,"props":1981,"children":1982},{"__ignoreMap":1581},[1983,2058,2107,2190,2206,2268,2299],{"type":45,"tag":1587,"props":1984,"children":1985},{"class":1589,"line":1590},[1986,1990,1994,1998,2002,2006,2010,2014,2018,2022,2026,2030,2034,2038,2042,2046,2050,2054],{"type":45,"tag":1587,"props":1987,"children":1988},{"style":1708},[1989],{"type":50,"value":1711},{"type":45,"tag":1587,"props":1991,"children":1992},{"style":1714},[1993],{"type":50,"value":132},{"type":45,"tag":1587,"props":1995,"children":1996},{"style":1719},[1997],{"type":50,"value":1722},{"type":45,"tag":1587,"props":1999,"children":2000},{"style":1708},[2001],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2003,"children":2004},{"style":1714},[2005],{"type":50,"value":1732},{"type":45,"tag":1587,"props":2007,"children":2008},{"style":1735},[2009],{"type":50,"value":1738},{"type":45,"tag":1587,"props":2011,"children":2012},{"style":1714},[2013],{"type":50,"value":1732},{"type":45,"tag":1587,"props":2015,"children":2016},{"style":1714},[2017],{"type":50,"value":1747},{"type":45,"tag":1587,"props":2019,"children":2020},{"style":1708},[2021],{"type":50,"value":1752},{"type":45,"tag":1587,"props":2023,"children":2024},{"style":1714},[2025],{"type":50,"value":1747},{"type":45,"tag":1587,"props":2027,"children":2028},{"style":1759},[2029],{"type":50,"value":1762},{"type":45,"tag":1587,"props":2031,"children":2032},{"style":1714},[2033],{"type":50,"value":1381},{"type":45,"tag":1587,"props":2035,"children":2036},{"style":1769},[2037],{"type":50,"value":1772},{"type":45,"tag":1587,"props":2039,"children":2040},{"style":1714},[2041],{"type":50,"value":1747},{"type":45,"tag":1587,"props":2043,"children":2044},{"style":1769},[2045],{"type":50,"value":1781},{"type":45,"tag":1587,"props":2047,"children":2048},{"style":1714},[2049],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2051,"children":2052},{"style":1759},[2053],{"type":50,"value":1791},{"type":45,"tag":1587,"props":2055,"children":2056},{"style":1714},[2057],{"type":50,"value":1796},{"type":45,"tag":1587,"props":2059,"children":2060},{"class":1589,"line":1599},[2061,2065,2069,2073,2077,2081,2085,2089,2093,2098,2102],{"type":45,"tag":1587,"props":2062,"children":2063},{"style":1759},[2064],{"type":50,"value":1804},{"type":45,"tag":1587,"props":2066,"children":2067},{"style":1708},[2068],{"type":50,"value":1809},{"type":45,"tag":1587,"props":2070,"children":2071},{"style":1714},[2072],{"type":50,"value":1814},{"type":45,"tag":1587,"props":2074,"children":2075},{"style":1817},[2076],{"type":50,"value":1820},{"type":45,"tag":1587,"props":2078,"children":2079},{"style":1708},[2080],{"type":50,"value":1825},{"type":45,"tag":1587,"props":2082,"children":2083},{"style":1714},[2084],{"type":50,"value":132},{"type":45,"tag":1587,"props":2086,"children":2087},{"style":1708},[2088],{"type":50,"value":1834},{"type":45,"tag":1587,"props":2090,"children":2091},{"style":1714},[2092],{"type":50,"value":132},{"type":45,"tag":1587,"props":2094,"children":2095},{"style":1719},[2096],{"type":50,"value":2097},"findFirst",{"type":45,"tag":1587,"props":2099,"children":2100},{"style":1846},[2101],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2103,"children":2104},{"style":1714},[2105],{"type":50,"value":2106},"{\n",{"type":45,"tag":1587,"props":2108,"children":2109},{"class":1589,"line":31},[2110,2115,2119,2123,2127,2131,2135,2139,2143,2147,2151,2155,2160,2164,2168,2172,2177,2181,2185],{"type":45,"tag":1587,"props":2111,"children":2112},{"style":1846},[2113],{"type":50,"value":2114},"    where",{"type":45,"tag":1587,"props":2116,"children":2117},{"style":1714},[2118],{"type":50,"value":1863},{"type":45,"tag":1587,"props":2120,"children":2121},{"style":1714},[2122],{"type":50,"value":1868},{"type":45,"tag":1587,"props":2124,"children":2125},{"style":1846},[2126],{"type":50,"value":1873},{"type":45,"tag":1587,"props":2128,"children":2129},{"style":1714},[2130],{"type":50,"value":1863},{"type":45,"tag":1587,"props":2132,"children":2133},{"style":1708},[2134],{"type":50,"value":1882},{"type":45,"tag":1587,"props":2136,"children":2137},{"style":1714},[2138],{"type":50,"value":132},{"type":45,"tag":1587,"props":2140,"children":2141},{"style":1708},[2142],{"type":50,"value":1891},{"type":45,"tag":1587,"props":2144,"children":2145},{"style":1714},[2146],{"type":50,"value":132},{"type":45,"tag":1587,"props":2148,"children":2149},{"style":1708},[2150],{"type":50,"value":1900},{"type":45,"tag":1587,"props":2152,"children":2153},{"style":1714},[2154],{"type":50,"value":1747},{"type":45,"tag":1587,"props":2156,"children":2157},{"style":1846},[2158],{"type":50,"value":2159}," userId",{"type":45,"tag":1587,"props":2161,"children":2162},{"style":1714},[2163],{"type":50,"value":1863},{"type":45,"tag":1587,"props":2165,"children":2166},{"style":1708},[2167],{"type":50,"value":1882},{"type":45,"tag":1587,"props":2169,"children":2170},{"style":1714},[2171],{"type":50,"value":132},{"type":45,"tag":1587,"props":2173,"children":2174},{"style":1708},[2175],{"type":50,"value":2176},"user",{"type":45,"tag":1587,"props":2178,"children":2179},{"style":1714},[2180],{"type":50,"value":132},{"type":45,"tag":1587,"props":2182,"children":2183},{"style":1708},[2184],{"type":50,"value":1900},{"type":45,"tag":1587,"props":2186,"children":2187},{"style":1714},[2188],{"type":50,"value":2189}," },\n",{"type":45,"tag":1587,"props":2191,"children":2192},{"class":1589,"line":1617},[2193,2198,2202],{"type":45,"tag":1587,"props":2194,"children":2195},{"style":1714},[2196],{"type":50,"value":2197},"  }",{"type":45,"tag":1587,"props":2199,"children":2200},{"style":1846},[2201],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2203,"children":2204},{"style":1714},[2205],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2207,"children":2208},{"class":1589,"line":1626},[2209,2214,2218,2223,2227,2232,2237,2241,2245,2250,2254,2260,2264],{"type":45,"tag":1587,"props":2210,"children":2211},{"style":1817},[2212],{"type":50,"value":2213},"  if",{"type":45,"tag":1587,"props":2215,"children":2216},{"style":1846},[2217],{"type":50,"value":1381},{"type":45,"tag":1587,"props":2219,"children":2220},{"style":1714},[2221],{"type":50,"value":2222},"!",{"type":45,"tag":1587,"props":2224,"children":2225},{"style":1708},[2226],{"type":50,"value":1834},{"type":45,"tag":1587,"props":2228,"children":2229},{"style":1846},[2230],{"type":50,"value":2231},") ",{"type":45,"tag":1587,"props":2233,"children":2234},{"style":1817},[2235],{"type":50,"value":2236},"return",{"type":45,"tag":1587,"props":2238,"children":2239},{"style":1708},[2240],{"type":50,"value":1781},{"type":45,"tag":1587,"props":2242,"children":2243},{"style":1714},[2244],{"type":50,"value":132},{"type":45,"tag":1587,"props":2246,"children":2247},{"style":1719},[2248],{"type":50,"value":2249},"sendStatus",{"type":45,"tag":1587,"props":2251,"children":2252},{"style":1846},[2253],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2255,"children":2257},{"style":2256},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[2258],{"type":50,"value":2259},"404",{"type":45,"tag":1587,"props":2261,"children":2262},{"style":1846},[2263],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2265,"children":2266},{"style":1714},[2267],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2269,"children":2270},{"class":1589,"line":1635},[2271,2275,2279,2283,2287,2291,2295],{"type":45,"tag":1587,"props":2272,"children":2273},{"style":1708},[2274],{"type":50,"value":1926},{"type":45,"tag":1587,"props":2276,"children":2277},{"style":1714},[2278],{"type":50,"value":132},{"type":45,"tag":1587,"props":2280,"children":2281},{"style":1719},[2282],{"type":50,"value":1935},{"type":45,"tag":1587,"props":2284,"children":2285},{"style":1846},[2286],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2288,"children":2289},{"style":1708},[2290],{"type":50,"value":1834},{"type":45,"tag":1587,"props":2292,"children":2293},{"style":1846},[2294],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2296,"children":2297},{"style":1714},[2298],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2300,"children":2302},{"class":1589,"line":2301},7,[2303,2307,2311],{"type":45,"tag":1587,"props":2304,"children":2305},{"style":1714},[2306],{"type":50,"value":1959},{"type":45,"tag":1587,"props":2308,"children":2309},{"style":1708},[2310],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2312,"children":2313},{"style":1714},[2314],{"type":50,"value":1918},{"type":45,"tag":1548,"props":2316,"children":2318},{"id":2317},"pattern-missing-tenant-scoping-on-a-viewset",[2319],{"type":50,"value":2320},"Pattern: Missing tenant scoping on a ViewSet",{"type":45,"tag":46,"props":2322,"children":2323},{},[2324,2326,2331],{"type":50,"value":2325},"The DRF default. Missing ",{"type":45,"tag":101,"props":2327,"children":2329},{"className":2328},[],[2330],{"type":50,"value":797},{"type":50,"value":2332}," override is the #1 IDOR shape in Django code.",{"type":45,"tag":46,"props":2334,"children":2335},{},[2336],{"type":45,"tag":66,"props":2337,"children":2338},{},[2339],{"type":50,"value":2340},"Python - bad:",{"type":45,"tag":1576,"props":2342,"children":2344},{"className":1578,"code":2343,"language":1580,"meta":1581,"style":1581},"class InvoiceViewSet(ModelViewSet):\n    queryset = Invoice.objects.all()\n    serializer_class = InvoiceSerializer\n    permission_classes = [IsAuthenticated]\n",[2345],{"type":45,"tag":101,"props":2346,"children":2347},{"__ignoreMap":1581},[2348,2356,2364,2372],{"type":45,"tag":1587,"props":2349,"children":2350},{"class":1589,"line":1590},[2351],{"type":45,"tag":1587,"props":2352,"children":2353},{},[2354],{"type":50,"value":2355},"class InvoiceViewSet(ModelViewSet):\n",{"type":45,"tag":1587,"props":2357,"children":2358},{"class":1589,"line":1599},[2359],{"type":45,"tag":1587,"props":2360,"children":2361},{},[2362],{"type":50,"value":2363},"    queryset = Invoice.objects.all()\n",{"type":45,"tag":1587,"props":2365,"children":2366},{"class":1589,"line":31},[2367],{"type":45,"tag":1587,"props":2368,"children":2369},{},[2370],{"type":50,"value":2371},"    serializer_class = InvoiceSerializer\n",{"type":45,"tag":1587,"props":2373,"children":2374},{"class":1589,"line":1617},[2375],{"type":45,"tag":1587,"props":2376,"children":2377},{},[2378],{"type":50,"value":1605},{"type":45,"tag":46,"props":2380,"children":2381},{},[2382],{"type":50,"value":2383},"Any authenticated user reads every invoice in the system.",{"type":45,"tag":46,"props":2385,"children":2386},{},[2387],{"type":45,"tag":66,"props":2388,"children":2389},{},[2390],{"type":50,"value":1654},{"type":45,"tag":1576,"props":2392,"children":2394},{"className":1578,"code":2393,"language":1580,"meta":1581,"style":1581},"class InvoiceViewSet(ModelViewSet):\n    serializer_class = InvoiceSerializer\n    permission_classes = [IsAuthenticated]\n\n    def get_queryset(self):\n        return Invoice.objects.filter(organization=self.request.user.organization)\n",[2395],{"type":45,"tag":101,"props":2396,"children":2397},{"__ignoreMap":1581},[2398,2405,2412,2419,2426,2434],{"type":45,"tag":1587,"props":2399,"children":2400},{"class":1589,"line":1590},[2401],{"type":45,"tag":1587,"props":2402,"children":2403},{},[2404],{"type":50,"value":2355},{"type":45,"tag":1587,"props":2406,"children":2407},{"class":1589,"line":1599},[2408],{"type":45,"tag":1587,"props":2409,"children":2410},{},[2411],{"type":50,"value":2371},{"type":45,"tag":1587,"props":2413,"children":2414},{"class":1589,"line":31},[2415],{"type":45,"tag":1587,"props":2416,"children":2417},{},[2418],{"type":50,"value":1605},{"type":45,"tag":1587,"props":2420,"children":2421},{"class":1589,"line":1617},[2422],{"type":45,"tag":1587,"props":2423,"children":2424},{"emptyLinePlaceholder":1611},[2425],{"type":50,"value":1614},{"type":45,"tag":1587,"props":2427,"children":2428},{"class":1589,"line":1626},[2429],{"type":45,"tag":1587,"props":2430,"children":2431},{},[2432],{"type":50,"value":2433},"    def get_queryset(self):\n",{"type":45,"tag":1587,"props":2435,"children":2436},{"class":1589,"line":1635},[2437],{"type":45,"tag":1587,"props":2438,"children":2439},{},[2440],{"type":50,"value":2441},"        return Invoice.objects.filter(organization=self.request.user.organization)\n",{"type":45,"tag":46,"props":2443,"children":2444},{},[2445],{"type":45,"tag":66,"props":2446,"children":2447},{},[2448],{"type":50,"value":2449},"TypeScript (NestJS) - bad:",{"type":45,"tag":1576,"props":2451,"children":2453},{"className":1696,"code":2452,"language":1698,"meta":1581,"style":1581},"@UseGuards(AuthGuard)\n@Get()\nfindAll() {\n  return this.invoiceService.findAll();\n}\n",[2454],{"type":45,"tag":101,"props":2455,"children":2456},{"__ignoreMap":1581},[2457,2475,2492,2509,2544],{"type":45,"tag":1587,"props":2458,"children":2459},{"class":1589,"line":1590},[2460,2465,2470],{"type":45,"tag":1587,"props":2461,"children":2462},{"style":1714},[2463],{"type":50,"value":2464},"@",{"type":45,"tag":1587,"props":2466,"children":2467},{"style":1719},[2468],{"type":50,"value":2469},"UseGuards",{"type":45,"tag":1587,"props":2471,"children":2472},{"style":1708},[2473],{"type":50,"value":2474},"(AuthGuard)\n",{"type":45,"tag":1587,"props":2476,"children":2477},{"class":1589,"line":1599},[2478,2482,2487],{"type":45,"tag":1587,"props":2479,"children":2480},{"style":1714},[2481],{"type":50,"value":2464},{"type":45,"tag":1587,"props":2483,"children":2484},{"style":1719},[2485],{"type":50,"value":2486},"Get",{"type":45,"tag":1587,"props":2488,"children":2489},{"style":1708},[2490],{"type":50,"value":2491},"()\n",{"type":45,"tag":1587,"props":2493,"children":2494},{"class":1589,"line":31},[2495,2500,2505],{"type":45,"tag":1587,"props":2496,"children":2497},{"style":1719},[2498],{"type":50,"value":2499},"findAll",{"type":45,"tag":1587,"props":2501,"children":2502},{"style":1708},[2503],{"type":50,"value":2504},"() ",{"type":45,"tag":1587,"props":2506,"children":2507},{"style":1714},[2508],{"type":50,"value":2106},{"type":45,"tag":1587,"props":2510,"children":2511},{"class":1589,"line":1617},[2512,2517,2522,2527,2531,2535,2540],{"type":45,"tag":1587,"props":2513,"children":2514},{"style":1817},[2515],{"type":50,"value":2516},"  return",{"type":45,"tag":1587,"props":2518,"children":2519},{"style":1714},[2520],{"type":50,"value":2521}," this.",{"type":45,"tag":1587,"props":2523,"children":2524},{"style":1708},[2525],{"type":50,"value":2526},"invoiceService",{"type":45,"tag":1587,"props":2528,"children":2529},{"style":1714},[2530],{"type":50,"value":132},{"type":45,"tag":1587,"props":2532,"children":2533},{"style":1719},[2534],{"type":50,"value":2499},{"type":45,"tag":1587,"props":2536,"children":2537},{"style":1846},[2538],{"type":50,"value":2539},"()",{"type":45,"tag":1587,"props":2541,"children":2542},{"style":1714},[2543],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2545,"children":2546},{"class":1589,"line":1626},[2547],{"type":45,"tag":1587,"props":2548,"children":2549},{"style":1714},[2550],{"type":50,"value":2551},"}\n",{"type":45,"tag":46,"props":2553,"children":2554},{},[2555],{"type":45,"tag":66,"props":2556,"children":2557},{},[2558],{"type":50,"value":1975},{"type":45,"tag":1576,"props":2560,"children":2562},{"className":1696,"code":2561,"language":1698,"meta":1581,"style":1581},"@UseGuards(AuthGuard)\n@Get()\nfindAll(@CurrentUser() user: User) {\n  return this.invoiceService.findAllForOrg(user.orgId);\n}\n",[2563],{"type":45,"tag":101,"props":2564,"children":2565},{"__ignoreMap":1581},[2566,2581,2596,2622,2671],{"type":45,"tag":1587,"props":2567,"children":2568},{"class":1589,"line":1590},[2569,2573,2577],{"type":45,"tag":1587,"props":2570,"children":2571},{"style":1714},[2572],{"type":50,"value":2464},{"type":45,"tag":1587,"props":2574,"children":2575},{"style":1719},[2576],{"type":50,"value":2469},{"type":45,"tag":1587,"props":2578,"children":2579},{"style":1708},[2580],{"type":50,"value":2474},{"type":45,"tag":1587,"props":2582,"children":2583},{"class":1589,"line":1599},[2584,2588,2592],{"type":45,"tag":1587,"props":2585,"children":2586},{"style":1714},[2587],{"type":50,"value":2464},{"type":45,"tag":1587,"props":2589,"children":2590},{"style":1719},[2591],{"type":50,"value":2486},{"type":45,"tag":1587,"props":2593,"children":2594},{"style":1708},[2595],{"type":50,"value":2491},{"type":45,"tag":1587,"props":2597,"children":2598},{"class":1589,"line":31},[2599,2603,2608,2613,2618],{"type":45,"tag":1587,"props":2600,"children":2601},{"style":1719},[2602],{"type":50,"value":2499},{"type":45,"tag":1587,"props":2604,"children":2605},{"style":1708},[2606],{"type":50,"value":2607},"(@",{"type":45,"tag":1587,"props":2609,"children":2610},{"style":1719},[2611],{"type":50,"value":2612},"CurrentUser",{"type":45,"tag":1587,"props":2614,"children":2615},{"style":1708},[2616],{"type":50,"value":2617},"() user: User) ",{"type":45,"tag":1587,"props":2619,"children":2620},{"style":1714},[2621],{"type":50,"value":2106},{"type":45,"tag":1587,"props":2623,"children":2624},{"class":1589,"line":1617},[2625,2629,2633,2637,2641,2646,2650,2654,2658,2663,2667],{"type":45,"tag":1587,"props":2626,"children":2627},{"style":1817},[2628],{"type":50,"value":2516},{"type":45,"tag":1587,"props":2630,"children":2631},{"style":1714},[2632],{"type":50,"value":2521},{"type":45,"tag":1587,"props":2634,"children":2635},{"style":1708},[2636],{"type":50,"value":2526},{"type":45,"tag":1587,"props":2638,"children":2639},{"style":1714},[2640],{"type":50,"value":132},{"type":45,"tag":1587,"props":2642,"children":2643},{"style":1719},[2644],{"type":50,"value":2645},"findAllForOrg",{"type":45,"tag":1587,"props":2647,"children":2648},{"style":1846},[2649],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2651,"children":2652},{"style":1708},[2653],{"type":50,"value":2176},{"type":45,"tag":1587,"props":2655,"children":2656},{"style":1714},[2657],{"type":50,"value":132},{"type":45,"tag":1587,"props":2659,"children":2660},{"style":1708},[2661],{"type":50,"value":2662},"orgId",{"type":45,"tag":1587,"props":2664,"children":2665},{"style":1846},[2666],{"type":50,"value":1786},{"type":45,"tag":1587,"props":2668,"children":2669},{"style":1714},[2670],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2672,"children":2673},{"class":1589,"line":1626},[2674],{"type":45,"tag":1587,"props":2675,"children":2676},{"style":1714},[2677],{"type":50,"value":2551},{"type":45,"tag":1548,"props":2679,"children":2681},{"id":2680},"pattern-role-check-fails-open",[2682],{"type":50,"value":2683},"Pattern: Role check fails open",{"type":45,"tag":46,"props":2685,"children":2686},{},[2687,2689,2694],{"type":50,"value":2688},"Real incident: Apollo Router CVE-2025-64347 — directive renamed via ",{"type":45,"tag":101,"props":2690,"children":2692},{"className":2691},[],[2693],{"type":50,"value":871},{"type":50,"value":2695}," wasn't recognized; default path allowed.",{"type":45,"tag":46,"props":2697,"children":2698},{},[2699],{"type":45,"tag":66,"props":2700,"children":2701},{},[2702],{"type":50,"value":2340},{"type":45,"tag":1576,"props":2704,"children":2706},{"className":1578,"code":2705,"language":1580,"meta":1581,"style":1581},"def can_edit(user, resource):\n    if user.role == \"admin\":\n        return True\n    if user.role == \"editor\" and resource.owner_id == user.id:\n        return True\n    # No final return. Returns None on any other role string.\n    # If the caller does `if not can_edit(...)` this behaves like False,\n    # but if the caller logs or serializes the result, None leaks through.\n",[2707],{"type":45,"tag":101,"props":2708,"children":2709},{"__ignoreMap":1581},[2710,2718,2726,2734,2742,2749,2757,2765],{"type":45,"tag":1587,"props":2711,"children":2712},{"class":1589,"line":1590},[2713],{"type":45,"tag":1587,"props":2714,"children":2715},{},[2716],{"type":50,"value":2717},"def can_edit(user, resource):\n",{"type":45,"tag":1587,"props":2719,"children":2720},{"class":1589,"line":1599},[2721],{"type":45,"tag":1587,"props":2722,"children":2723},{},[2724],{"type":50,"value":2725},"    if user.role == \"admin\":\n",{"type":45,"tag":1587,"props":2727,"children":2728},{"class":1589,"line":31},[2729],{"type":45,"tag":1587,"props":2730,"children":2731},{},[2732],{"type":50,"value":2733},"        return True\n",{"type":45,"tag":1587,"props":2735,"children":2736},{"class":1589,"line":1617},[2737],{"type":45,"tag":1587,"props":2738,"children":2739},{},[2740],{"type":50,"value":2741},"    if user.role == \"editor\" and resource.owner_id == user.id:\n",{"type":45,"tag":1587,"props":2743,"children":2744},{"class":1589,"line":1626},[2745],{"type":45,"tag":1587,"props":2746,"children":2747},{},[2748],{"type":50,"value":2733},{"type":45,"tag":1587,"props":2750,"children":2751},{"class":1589,"line":1635},[2752],{"type":45,"tag":1587,"props":2753,"children":2754},{},[2755],{"type":50,"value":2756},"    # No final return. Returns None on any other role string.\n",{"type":45,"tag":1587,"props":2758,"children":2759},{"class":1589,"line":2301},[2760],{"type":45,"tag":1587,"props":2761,"children":2762},{},[2763],{"type":50,"value":2764},"    # If the caller does `if not can_edit(...)` this behaves like False,\n",{"type":45,"tag":1587,"props":2766,"children":2768},{"class":1589,"line":2767},8,[2769],{"type":45,"tag":1587,"props":2770,"children":2771},{},[2772],{"type":50,"value":2773},"    # but if the caller logs or serializes the result, None leaks through.\n",{"type":45,"tag":46,"props":2775,"children":2776},{},[2777],{"type":45,"tag":66,"props":2778,"children":2779},{},[2780],{"type":50,"value":1654},{"type":45,"tag":1576,"props":2782,"children":2784},{"className":1578,"code":2783,"language":1580,"meta":1581,"style":1581},"def can_edit(user, resource):\n    if user.role == \"admin\":\n        return True\n    if user.role == \"editor\" and resource.owner_id == user.id:\n        return True\n    return False\n",[2785],{"type":45,"tag":101,"props":2786,"children":2787},{"__ignoreMap":1581},[2788,2795,2802,2809,2816,2823],{"type":45,"tag":1587,"props":2789,"children":2790},{"class":1589,"line":1590},[2791],{"type":45,"tag":1587,"props":2792,"children":2793},{},[2794],{"type":50,"value":2717},{"type":45,"tag":1587,"props":2796,"children":2797},{"class":1589,"line":1599},[2798],{"type":45,"tag":1587,"props":2799,"children":2800},{},[2801],{"type":50,"value":2725},{"type":45,"tag":1587,"props":2803,"children":2804},{"class":1589,"line":31},[2805],{"type":45,"tag":1587,"props":2806,"children":2807},{},[2808],{"type":50,"value":2733},{"type":45,"tag":1587,"props":2810,"children":2811},{"class":1589,"line":1617},[2812],{"type":45,"tag":1587,"props":2813,"children":2814},{},[2815],{"type":50,"value":2741},{"type":45,"tag":1587,"props":2817,"children":2818},{"class":1589,"line":1626},[2819],{"type":45,"tag":1587,"props":2820,"children":2821},{},[2822],{"type":50,"value":2733},{"type":45,"tag":1587,"props":2824,"children":2825},{"class":1589,"line":1635},[2826],{"type":45,"tag":1587,"props":2827,"children":2828},{},[2829],{"type":50,"value":2830},"    return False\n",{"type":45,"tag":46,"props":2832,"children":2833},{},[2834],{"type":45,"tag":66,"props":2835,"children":2836},{},[2837],{"type":50,"value":2838},"TypeScript - bad:",{"type":45,"tag":1576,"props":2840,"children":2842},{"className":1696,"code":2841,"language":1698,"meta":1581,"style":1581},"function canEdit(user: User, resource: Resource): boolean {\n  if (user.role === 'admin') return true;\n  if (user.role === 'editor' && resource.ownerId === user.id) return true;\n  return user.role !== 'banned'; \u002F\u002F Fail-open default. Anyone not banned edits.\n}\n",[2843],{"type":45,"tag":101,"props":2844,"children":2845},{"__ignoreMap":1581},[2846,2909,2970,3061,3109],{"type":45,"tag":1587,"props":2847,"children":2848},{"class":1589,"line":1590},[2849,2854,2859,2863,2867,2871,2877,2881,2886,2890,2895,2900,2905],{"type":45,"tag":1587,"props":2850,"children":2851},{"style":1759},[2852],{"type":50,"value":2853},"function",{"type":45,"tag":1587,"props":2855,"children":2856},{"style":1719},[2857],{"type":50,"value":2858}," canEdit",{"type":45,"tag":1587,"props":2860,"children":2861},{"style":1714},[2862],{"type":50,"value":1727},{"type":45,"tag":1587,"props":2864,"children":2865},{"style":1769},[2866],{"type":50,"value":2176},{"type":45,"tag":1587,"props":2868,"children":2869},{"style":1714},[2870],{"type":50,"value":1863},{"type":45,"tag":1587,"props":2872,"children":2874},{"style":2873},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[2875],{"type":50,"value":2876}," User",{"type":45,"tag":1587,"props":2878,"children":2879},{"style":1714},[2880],{"type":50,"value":1747},{"type":45,"tag":1587,"props":2882,"children":2883},{"style":1769},[2884],{"type":50,"value":2885}," resource",{"type":45,"tag":1587,"props":2887,"children":2888},{"style":1714},[2889],{"type":50,"value":1863},{"type":45,"tag":1587,"props":2891,"children":2892},{"style":2873},[2893],{"type":50,"value":2894}," Resource",{"type":45,"tag":1587,"props":2896,"children":2897},{"style":1714},[2898],{"type":50,"value":2899},"):",{"type":45,"tag":1587,"props":2901,"children":2902},{"style":2873},[2903],{"type":50,"value":2904}," boolean",{"type":45,"tag":1587,"props":2906,"children":2907},{"style":1714},[2908],{"type":50,"value":1796},{"type":45,"tag":1587,"props":2910,"children":2911},{"class":1589,"line":1599},[2912,2916,2920,2924,2928,2933,2938,2943,2948,2952,2956,2960,2966],{"type":45,"tag":1587,"props":2913,"children":2914},{"style":1817},[2915],{"type":50,"value":2213},{"type":45,"tag":1587,"props":2917,"children":2918},{"style":1846},[2919],{"type":50,"value":1381},{"type":45,"tag":1587,"props":2921,"children":2922},{"style":1708},[2923],{"type":50,"value":2176},{"type":45,"tag":1587,"props":2925,"children":2926},{"style":1714},[2927],{"type":50,"value":132},{"type":45,"tag":1587,"props":2929,"children":2930},{"style":1708},[2931],{"type":50,"value":2932},"role",{"type":45,"tag":1587,"props":2934,"children":2935},{"style":1714},[2936],{"type":50,"value":2937}," ===",{"type":45,"tag":1587,"props":2939,"children":2940},{"style":1714},[2941],{"type":50,"value":2942}," '",{"type":45,"tag":1587,"props":2944,"children":2945},{"style":1735},[2946],{"type":50,"value":2947},"admin",{"type":45,"tag":1587,"props":2949,"children":2950},{"style":1714},[2951],{"type":50,"value":1732},{"type":45,"tag":1587,"props":2953,"children":2954},{"style":1846},[2955],{"type":50,"value":2231},{"type":45,"tag":1587,"props":2957,"children":2958},{"style":1817},[2959],{"type":50,"value":2236},{"type":45,"tag":1587,"props":2961,"children":2963},{"style":2962},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[2964],{"type":50,"value":2965}," true",{"type":45,"tag":1587,"props":2967,"children":2968},{"style":1714},[2969],{"type":50,"value":1918},{"type":45,"tag":1587,"props":2971,"children":2972},{"class":1589,"line":31},[2973,2977,2981,2985,2989,2993,2997,3001,3006,3010,3015,3019,3023,3028,3032,3037,3041,3045,3049,3053,3057],{"type":45,"tag":1587,"props":2974,"children":2975},{"style":1817},[2976],{"type":50,"value":2213},{"type":45,"tag":1587,"props":2978,"children":2979},{"style":1846},[2980],{"type":50,"value":1381},{"type":45,"tag":1587,"props":2982,"children":2983},{"style":1708},[2984],{"type":50,"value":2176},{"type":45,"tag":1587,"props":2986,"children":2987},{"style":1714},[2988],{"type":50,"value":132},{"type":45,"tag":1587,"props":2990,"children":2991},{"style":1708},[2992],{"type":50,"value":2932},{"type":45,"tag":1587,"props":2994,"children":2995},{"style":1714},[2996],{"type":50,"value":2937},{"type":45,"tag":1587,"props":2998,"children":2999},{"style":1714},[3000],{"type":50,"value":2942},{"type":45,"tag":1587,"props":3002,"children":3003},{"style":1735},[3004],{"type":50,"value":3005},"editor",{"type":45,"tag":1587,"props":3007,"children":3008},{"style":1714},[3009],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3011,"children":3012},{"style":1714},[3013],{"type":50,"value":3014}," &&",{"type":45,"tag":1587,"props":3016,"children":3017},{"style":1708},[3018],{"type":50,"value":2885},{"type":45,"tag":1587,"props":3020,"children":3021},{"style":1714},[3022],{"type":50,"value":132},{"type":45,"tag":1587,"props":3024,"children":3025},{"style":1708},[3026],{"type":50,"value":3027},"ownerId",{"type":45,"tag":1587,"props":3029,"children":3030},{"style":1714},[3031],{"type":50,"value":2937},{"type":45,"tag":1587,"props":3033,"children":3034},{"style":1708},[3035],{"type":50,"value":3036}," user",{"type":45,"tag":1587,"props":3038,"children":3039},{"style":1714},[3040],{"type":50,"value":132},{"type":45,"tag":1587,"props":3042,"children":3043},{"style":1708},[3044],{"type":50,"value":1900},{"type":45,"tag":1587,"props":3046,"children":3047},{"style":1846},[3048],{"type":50,"value":2231},{"type":45,"tag":1587,"props":3050,"children":3051},{"style":1817},[3052],{"type":50,"value":2236},{"type":45,"tag":1587,"props":3054,"children":3055},{"style":2962},[3056],{"type":50,"value":2965},{"type":45,"tag":1587,"props":3058,"children":3059},{"style":1714},[3060],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3062,"children":3063},{"class":1589,"line":1617},[3064,3068,3072,3076,3080,3085,3089,3094,3098,3103],{"type":45,"tag":1587,"props":3065,"children":3066},{"style":1817},[3067],{"type":50,"value":2516},{"type":45,"tag":1587,"props":3069,"children":3070},{"style":1708},[3071],{"type":50,"value":3036},{"type":45,"tag":1587,"props":3073,"children":3074},{"style":1714},[3075],{"type":50,"value":132},{"type":45,"tag":1587,"props":3077,"children":3078},{"style":1708},[3079],{"type":50,"value":2932},{"type":45,"tag":1587,"props":3081,"children":3082},{"style":1714},[3083],{"type":50,"value":3084}," !==",{"type":45,"tag":1587,"props":3086,"children":3087},{"style":1714},[3088],{"type":50,"value":2942},{"type":45,"tag":1587,"props":3090,"children":3091},{"style":1735},[3092],{"type":50,"value":3093},"banned",{"type":45,"tag":1587,"props":3095,"children":3096},{"style":1714},[3097],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3099,"children":3100},{"style":1714},[3101],{"type":50,"value":3102},";",{"type":45,"tag":1587,"props":3104,"children":3106},{"style":3105},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[3107],{"type":50,"value":3108}," \u002F\u002F Fail-open default. Anyone not banned edits.\n",{"type":45,"tag":1587,"props":3110,"children":3111},{"class":1589,"line":1626},[3112],{"type":45,"tag":1587,"props":3113,"children":3114},{"style":1714},[3115],{"type":50,"value":2551},{"type":45,"tag":46,"props":3117,"children":3118},{},[3119],{"type":45,"tag":66,"props":3120,"children":3121},{},[3122],{"type":50,"value":1975},{"type":45,"tag":1576,"props":3124,"children":3126},{"className":1696,"code":3125,"language":1698,"meta":1581,"style":1581},"function canEdit(user: User, resource: Resource): boolean {\n  if (user.role === 'admin') return true;\n  if (user.role === 'editor' && resource.ownerId === user.id) return true;\n  return false;\n}\n",[3127],{"type":45,"tag":101,"props":3128,"children":3129},{"__ignoreMap":1581},[3130,3185,3240,3327,3343],{"type":45,"tag":1587,"props":3131,"children":3132},{"class":1589,"line":1590},[3133,3137,3141,3145,3149,3153,3157,3161,3165,3169,3173,3177,3181],{"type":45,"tag":1587,"props":3134,"children":3135},{"style":1759},[3136],{"type":50,"value":2853},{"type":45,"tag":1587,"props":3138,"children":3139},{"style":1719},[3140],{"type":50,"value":2858},{"type":45,"tag":1587,"props":3142,"children":3143},{"style":1714},[3144],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3146,"children":3147},{"style":1769},[3148],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3150,"children":3151},{"style":1714},[3152],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3154,"children":3155},{"style":2873},[3156],{"type":50,"value":2876},{"type":45,"tag":1587,"props":3158,"children":3159},{"style":1714},[3160],{"type":50,"value":1747},{"type":45,"tag":1587,"props":3162,"children":3163},{"style":1769},[3164],{"type":50,"value":2885},{"type":45,"tag":1587,"props":3166,"children":3167},{"style":1714},[3168],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3170,"children":3171},{"style":2873},[3172],{"type":50,"value":2894},{"type":45,"tag":1587,"props":3174,"children":3175},{"style":1714},[3176],{"type":50,"value":2899},{"type":45,"tag":1587,"props":3178,"children":3179},{"style":2873},[3180],{"type":50,"value":2904},{"type":45,"tag":1587,"props":3182,"children":3183},{"style":1714},[3184],{"type":50,"value":1796},{"type":45,"tag":1587,"props":3186,"children":3187},{"class":1589,"line":1599},[3188,3192,3196,3200,3204,3208,3212,3216,3220,3224,3228,3232,3236],{"type":45,"tag":1587,"props":3189,"children":3190},{"style":1817},[3191],{"type":50,"value":2213},{"type":45,"tag":1587,"props":3193,"children":3194},{"style":1846},[3195],{"type":50,"value":1381},{"type":45,"tag":1587,"props":3197,"children":3198},{"style":1708},[3199],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3201,"children":3202},{"style":1714},[3203],{"type":50,"value":132},{"type":45,"tag":1587,"props":3205,"children":3206},{"style":1708},[3207],{"type":50,"value":2932},{"type":45,"tag":1587,"props":3209,"children":3210},{"style":1714},[3211],{"type":50,"value":2937},{"type":45,"tag":1587,"props":3213,"children":3214},{"style":1714},[3215],{"type":50,"value":2942},{"type":45,"tag":1587,"props":3217,"children":3218},{"style":1735},[3219],{"type":50,"value":2947},{"type":45,"tag":1587,"props":3221,"children":3222},{"style":1714},[3223],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3225,"children":3226},{"style":1846},[3227],{"type":50,"value":2231},{"type":45,"tag":1587,"props":3229,"children":3230},{"style":1817},[3231],{"type":50,"value":2236},{"type":45,"tag":1587,"props":3233,"children":3234},{"style":2962},[3235],{"type":50,"value":2965},{"type":45,"tag":1587,"props":3237,"children":3238},{"style":1714},[3239],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3241,"children":3242},{"class":1589,"line":31},[3243,3247,3251,3255,3259,3263,3267,3271,3275,3279,3283,3287,3291,3295,3299,3303,3307,3311,3315,3319,3323],{"type":45,"tag":1587,"props":3244,"children":3245},{"style":1817},[3246],{"type":50,"value":2213},{"type":45,"tag":1587,"props":3248,"children":3249},{"style":1846},[3250],{"type":50,"value":1381},{"type":45,"tag":1587,"props":3252,"children":3253},{"style":1708},[3254],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3256,"children":3257},{"style":1714},[3258],{"type":50,"value":132},{"type":45,"tag":1587,"props":3260,"children":3261},{"style":1708},[3262],{"type":50,"value":2932},{"type":45,"tag":1587,"props":3264,"children":3265},{"style":1714},[3266],{"type":50,"value":2937},{"type":45,"tag":1587,"props":3268,"children":3269},{"style":1714},[3270],{"type":50,"value":2942},{"type":45,"tag":1587,"props":3272,"children":3273},{"style":1735},[3274],{"type":50,"value":3005},{"type":45,"tag":1587,"props":3276,"children":3277},{"style":1714},[3278],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3280,"children":3281},{"style":1714},[3282],{"type":50,"value":3014},{"type":45,"tag":1587,"props":3284,"children":3285},{"style":1708},[3286],{"type":50,"value":2885},{"type":45,"tag":1587,"props":3288,"children":3289},{"style":1714},[3290],{"type":50,"value":132},{"type":45,"tag":1587,"props":3292,"children":3293},{"style":1708},[3294],{"type":50,"value":3027},{"type":45,"tag":1587,"props":3296,"children":3297},{"style":1714},[3298],{"type":50,"value":2937},{"type":45,"tag":1587,"props":3300,"children":3301},{"style":1708},[3302],{"type":50,"value":3036},{"type":45,"tag":1587,"props":3304,"children":3305},{"style":1714},[3306],{"type":50,"value":132},{"type":45,"tag":1587,"props":3308,"children":3309},{"style":1708},[3310],{"type":50,"value":1900},{"type":45,"tag":1587,"props":3312,"children":3313},{"style":1846},[3314],{"type":50,"value":2231},{"type":45,"tag":1587,"props":3316,"children":3317},{"style":1817},[3318],{"type":50,"value":2236},{"type":45,"tag":1587,"props":3320,"children":3321},{"style":2962},[3322],{"type":50,"value":2965},{"type":45,"tag":1587,"props":3324,"children":3325},{"style":1714},[3326],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3328,"children":3329},{"class":1589,"line":1617},[3330,3334,3339],{"type":45,"tag":1587,"props":3331,"children":3332},{"style":1817},[3333],{"type":50,"value":2516},{"type":45,"tag":1587,"props":3335,"children":3336},{"style":2962},[3337],{"type":50,"value":3338}," false",{"type":45,"tag":1587,"props":3340,"children":3341},{"style":1714},[3342],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3344,"children":3345},{"class":1589,"line":1626},[3346],{"type":45,"tag":1587,"props":3347,"children":3348},{"style":1714},[3349],{"type":50,"value":2551},{"type":45,"tag":1548,"props":3351,"children":3353},{"id":3352},"pattern-mass-assignment-enabling-role-elevation",[3354],{"type":50,"value":3355},"Pattern: Mass assignment enabling role elevation",{"type":45,"tag":46,"props":3357,"children":3358},{},[3359,3361,3366,3368,3373],{"type":50,"value":3360},"Recurs constantly. Snyk's canonical Node.js mass-assignment writeup covers the ",{"type":45,"tag":101,"props":3362,"children":3364},{"className":3363},[],[3365],{"type":50,"value":914},{"type":50,"value":3367}," shape; OWASP's cheat sheet covers the DRF ",{"type":45,"tag":101,"props":3369,"children":3371},{"className":3370},[],[3372],{"type":50,"value":930},{"type":50,"value":3374}," shape.",{"type":45,"tag":46,"props":3376,"children":3377},{},[3378],{"type":45,"tag":66,"props":3379,"children":3380},{},[3381],{"type":50,"value":3382},"Python (DRF) - bad:",{"type":45,"tag":1576,"props":3384,"children":3386},{"className":1578,"code":3385,"language":1580,"meta":1581,"style":1581},"class UserSerializer(ModelSerializer):\n    class Meta:\n        model = User\n        fields = '__all__'  # Includes is_staff, is_superuser, organization_id.\n",[3387],{"type":45,"tag":101,"props":3388,"children":3389},{"__ignoreMap":1581},[3390,3398,3406,3414],{"type":45,"tag":1587,"props":3391,"children":3392},{"class":1589,"line":1590},[3393],{"type":45,"tag":1587,"props":3394,"children":3395},{},[3396],{"type":50,"value":3397},"class UserSerializer(ModelSerializer):\n",{"type":45,"tag":1587,"props":3399,"children":3400},{"class":1589,"line":1599},[3401],{"type":45,"tag":1587,"props":3402,"children":3403},{},[3404],{"type":50,"value":3405},"    class Meta:\n",{"type":45,"tag":1587,"props":3407,"children":3408},{"class":1589,"line":31},[3409],{"type":45,"tag":1587,"props":3410,"children":3411},{},[3412],{"type":50,"value":3413},"        model = User\n",{"type":45,"tag":1587,"props":3415,"children":3416},{"class":1589,"line":1617},[3417],{"type":45,"tag":1587,"props":3418,"children":3419},{},[3420],{"type":50,"value":3421},"        fields = '__all__'  # Includes is_staff, is_superuser, organization_id.\n",{"type":45,"tag":46,"props":3423,"children":3424},{},[3425],{"type":50,"value":3426},"Writable via a PATCH to the user's profile endpoint.",{"type":45,"tag":46,"props":3428,"children":3429},{},[3430],{"type":45,"tag":66,"props":3431,"children":3432},{},[3433],{"type":50,"value":1654},{"type":45,"tag":1576,"props":3435,"children":3437},{"className":1578,"code":3436,"language":1580,"meta":1581,"style":1581},"class UserProfileSerializer(ModelSerializer):\n    class Meta:\n        model = User\n        fields = ['display_name', 'avatar_url', 'timezone']\n",[3438],{"type":45,"tag":101,"props":3439,"children":3440},{"__ignoreMap":1581},[3441,3449,3456,3463],{"type":45,"tag":1587,"props":3442,"children":3443},{"class":1589,"line":1590},[3444],{"type":45,"tag":1587,"props":3445,"children":3446},{},[3447],{"type":50,"value":3448},"class UserProfileSerializer(ModelSerializer):\n",{"type":45,"tag":1587,"props":3450,"children":3451},{"class":1589,"line":1599},[3452],{"type":45,"tag":1587,"props":3453,"children":3454},{},[3455],{"type":50,"value":3405},{"type":45,"tag":1587,"props":3457,"children":3458},{"class":1589,"line":31},[3459],{"type":45,"tag":1587,"props":3460,"children":3461},{},[3462],{"type":50,"value":3413},{"type":45,"tag":1587,"props":3464,"children":3465},{"class":1589,"line":1617},[3466],{"type":45,"tag":1587,"props":3467,"children":3468},{},[3469],{"type":50,"value":3470},"        fields = ['display_name', 'avatar_url', 'timezone']\n",{"type":45,"tag":46,"props":3472,"children":3473},{},[3474],{"type":45,"tag":66,"props":3475,"children":3476},{},[3477],{"type":50,"value":1693},{"type":45,"tag":1576,"props":3479,"children":3481},{"className":1696,"code":3480,"language":1698,"meta":1581,"style":1581},"router.patch('\u002Fme', requireAuth, async (req, res) => {\n  const user = await db.user.update({\n    where: { id: req.user.id },\n    data: req.body,  \u002F\u002F {\"role\": \"ADMIN\"} promotes the caller.\n  });\n  res.json(user);\n});\n",[3482],{"type":45,"tag":101,"props":3483,"children":3484},{"__ignoreMap":1581},[3485,3562,3610,3657,3691,3706,3737],{"type":45,"tag":1587,"props":3486,"children":3487},{"class":1589,"line":1590},[3488,3492,3496,3501,3505,3509,3514,3518,3522,3526,3530,3534,3538,3542,3546,3550,3554,3558],{"type":45,"tag":1587,"props":3489,"children":3490},{"style":1708},[3491],{"type":50,"value":1711},{"type":45,"tag":1587,"props":3493,"children":3494},{"style":1714},[3495],{"type":50,"value":132},{"type":45,"tag":1587,"props":3497,"children":3498},{"style":1719},[3499],{"type":50,"value":3500},"patch",{"type":45,"tag":1587,"props":3502,"children":3503},{"style":1708},[3504],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3506,"children":3507},{"style":1714},[3508],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3510,"children":3511},{"style":1735},[3512],{"type":50,"value":3513},"\u002Fme",{"type":45,"tag":1587,"props":3515,"children":3516},{"style":1714},[3517],{"type":50,"value":1732},{"type":45,"tag":1587,"props":3519,"children":3520},{"style":1714},[3521],{"type":50,"value":1747},{"type":45,"tag":1587,"props":3523,"children":3524},{"style":1708},[3525],{"type":50,"value":1752},{"type":45,"tag":1587,"props":3527,"children":3528},{"style":1714},[3529],{"type":50,"value":1747},{"type":45,"tag":1587,"props":3531,"children":3532},{"style":1759},[3533],{"type":50,"value":1762},{"type":45,"tag":1587,"props":3535,"children":3536},{"style":1714},[3537],{"type":50,"value":1381},{"type":45,"tag":1587,"props":3539,"children":3540},{"style":1769},[3541],{"type":50,"value":1772},{"type":45,"tag":1587,"props":3543,"children":3544},{"style":1714},[3545],{"type":50,"value":1747},{"type":45,"tag":1587,"props":3547,"children":3548},{"style":1769},[3549],{"type":50,"value":1781},{"type":45,"tag":1587,"props":3551,"children":3552},{"style":1714},[3553],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3555,"children":3556},{"style":1759},[3557],{"type":50,"value":1791},{"type":45,"tag":1587,"props":3559,"children":3560},{"style":1714},[3561],{"type":50,"value":1796},{"type":45,"tag":1587,"props":3563,"children":3564},{"class":1589,"line":1599},[3565,3569,3573,3577,3581,3585,3589,3593,3597,3602,3606],{"type":45,"tag":1587,"props":3566,"children":3567},{"style":1759},[3568],{"type":50,"value":1804},{"type":45,"tag":1587,"props":3570,"children":3571},{"style":1708},[3572],{"type":50,"value":3036},{"type":45,"tag":1587,"props":3574,"children":3575},{"style":1714},[3576],{"type":50,"value":1814},{"type":45,"tag":1587,"props":3578,"children":3579},{"style":1817},[3580],{"type":50,"value":1820},{"type":45,"tag":1587,"props":3582,"children":3583},{"style":1708},[3584],{"type":50,"value":1825},{"type":45,"tag":1587,"props":3586,"children":3587},{"style":1714},[3588],{"type":50,"value":132},{"type":45,"tag":1587,"props":3590,"children":3591},{"style":1708},[3592],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3594,"children":3595},{"style":1714},[3596],{"type":50,"value":132},{"type":45,"tag":1587,"props":3598,"children":3599},{"style":1719},[3600],{"type":50,"value":3601},"update",{"type":45,"tag":1587,"props":3603,"children":3604},{"style":1846},[3605],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3607,"children":3608},{"style":1714},[3609],{"type":50,"value":2106},{"type":45,"tag":1587,"props":3611,"children":3612},{"class":1589,"line":31},[3613,3617,3621,3625,3629,3633,3637,3641,3645,3649,3653],{"type":45,"tag":1587,"props":3614,"children":3615},{"style":1846},[3616],{"type":50,"value":2114},{"type":45,"tag":1587,"props":3618,"children":3619},{"style":1714},[3620],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3622,"children":3623},{"style":1714},[3624],{"type":50,"value":1868},{"type":45,"tag":1587,"props":3626,"children":3627},{"style":1846},[3628],{"type":50,"value":1873},{"type":45,"tag":1587,"props":3630,"children":3631},{"style":1714},[3632],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3634,"children":3635},{"style":1708},[3636],{"type":50,"value":1882},{"type":45,"tag":1587,"props":3638,"children":3639},{"style":1714},[3640],{"type":50,"value":132},{"type":45,"tag":1587,"props":3642,"children":3643},{"style":1708},[3644],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3646,"children":3647},{"style":1714},[3648],{"type":50,"value":132},{"type":45,"tag":1587,"props":3650,"children":3651},{"style":1708},[3652],{"type":50,"value":1900},{"type":45,"tag":1587,"props":3654,"children":3655},{"style":1714},[3656],{"type":50,"value":2189},{"type":45,"tag":1587,"props":3658,"children":3659},{"class":1589,"line":1617},[3660,3665,3669,3673,3677,3682,3686],{"type":45,"tag":1587,"props":3661,"children":3662},{"style":1846},[3663],{"type":50,"value":3664},"    data",{"type":45,"tag":1587,"props":3666,"children":3667},{"style":1714},[3668],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3670,"children":3671},{"style":1708},[3672],{"type":50,"value":1882},{"type":45,"tag":1587,"props":3674,"children":3675},{"style":1714},[3676],{"type":50,"value":132},{"type":45,"tag":1587,"props":3678,"children":3679},{"style":1708},[3680],{"type":50,"value":3681},"body",{"type":45,"tag":1587,"props":3683,"children":3684},{"style":1714},[3685],{"type":50,"value":1747},{"type":45,"tag":1587,"props":3687,"children":3688},{"style":3105},[3689],{"type":50,"value":3690},"  \u002F\u002F {\"role\": \"ADMIN\"} promotes the caller.\n",{"type":45,"tag":1587,"props":3692,"children":3693},{"class":1589,"line":1626},[3694,3698,3702],{"type":45,"tag":1587,"props":3695,"children":3696},{"style":1714},[3697],{"type":50,"value":2197},{"type":45,"tag":1587,"props":3699,"children":3700},{"style":1846},[3701],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3703,"children":3704},{"style":1714},[3705],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3707,"children":3708},{"class":1589,"line":1635},[3709,3713,3717,3721,3725,3729,3733],{"type":45,"tag":1587,"props":3710,"children":3711},{"style":1708},[3712],{"type":50,"value":1926},{"type":45,"tag":1587,"props":3714,"children":3715},{"style":1714},[3716],{"type":50,"value":132},{"type":45,"tag":1587,"props":3718,"children":3719},{"style":1719},[3720],{"type":50,"value":1935},{"type":45,"tag":1587,"props":3722,"children":3723},{"style":1846},[3724],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3726,"children":3727},{"style":1708},[3728],{"type":50,"value":2176},{"type":45,"tag":1587,"props":3730,"children":3731},{"style":1846},[3732],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3734,"children":3735},{"style":1714},[3736],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3738,"children":3739},{"class":1589,"line":2301},[3740,3744,3748],{"type":45,"tag":1587,"props":3741,"children":3742},{"style":1714},[3743],{"type":50,"value":1959},{"type":45,"tag":1587,"props":3745,"children":3746},{"style":1708},[3747],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3749,"children":3750},{"style":1714},[3751],{"type":50,"value":1918},{"type":45,"tag":46,"props":3753,"children":3754},{},[3755],{"type":45,"tag":66,"props":3756,"children":3757},{},[3758],{"type":50,"value":1975},{"type":45,"tag":1576,"props":3760,"children":3762},{"className":1696,"code":3761,"language":1698,"meta":1581,"style":1581},"const ProfileUpdate = z.object({\n  displayName: z.string().max(80).optional(),\n  avatarUrl: z.string().url().optional(),\n  timezone: z.string().optional(),\n});\n\nrouter.patch('\u002Fme', requireAuth, async (req, res) => {\n  const data = ProfileUpdate.parse(req.body);\n  const user = await db.user.update({ where: { id: req.user.id }, data });\n  res.json(user);\n});\n",[3763],{"type":45,"tag":101,"props":3764,"children":3765},{"__ignoreMap":1581},[3766,3806,3875,3932,3976,3991,3998,4073,4127,4236,4268],{"type":45,"tag":1587,"props":3767,"children":3768},{"class":1589,"line":1590},[3769,3774,3779,3784,3789,3793,3798,3802],{"type":45,"tag":1587,"props":3770,"children":3771},{"style":1759},[3772],{"type":50,"value":3773},"const",{"type":45,"tag":1587,"props":3775,"children":3776},{"style":1708},[3777],{"type":50,"value":3778}," ProfileUpdate ",{"type":45,"tag":1587,"props":3780,"children":3781},{"style":1714},[3782],{"type":50,"value":3783},"=",{"type":45,"tag":1587,"props":3785,"children":3786},{"style":1708},[3787],{"type":50,"value":3788}," z",{"type":45,"tag":1587,"props":3790,"children":3791},{"style":1714},[3792],{"type":50,"value":132},{"type":45,"tag":1587,"props":3794,"children":3795},{"style":1719},[3796],{"type":50,"value":3797},"object",{"type":45,"tag":1587,"props":3799,"children":3800},{"style":1708},[3801],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3803,"children":3804},{"style":1714},[3805],{"type":50,"value":2106},{"type":45,"tag":1587,"props":3807,"children":3808},{"class":1589,"line":1599},[3809,3814,3818,3822,3826,3831,3835,3839,3844,3848,3853,3857,3861,3866,3870],{"type":45,"tag":1587,"props":3810,"children":3811},{"style":1846},[3812],{"type":50,"value":3813},"  displayName",{"type":45,"tag":1587,"props":3815,"children":3816},{"style":1714},[3817],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3819,"children":3820},{"style":1708},[3821],{"type":50,"value":3788},{"type":45,"tag":1587,"props":3823,"children":3824},{"style":1714},[3825],{"type":50,"value":132},{"type":45,"tag":1587,"props":3827,"children":3828},{"style":1719},[3829],{"type":50,"value":3830},"string",{"type":45,"tag":1587,"props":3832,"children":3833},{"style":1708},[3834],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3836,"children":3837},{"style":1714},[3838],{"type":50,"value":132},{"type":45,"tag":1587,"props":3840,"children":3841},{"style":1719},[3842],{"type":50,"value":3843},"max",{"type":45,"tag":1587,"props":3845,"children":3846},{"style":1708},[3847],{"type":50,"value":1727},{"type":45,"tag":1587,"props":3849,"children":3850},{"style":2256},[3851],{"type":50,"value":3852},"80",{"type":45,"tag":1587,"props":3854,"children":3855},{"style":1708},[3856],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3858,"children":3859},{"style":1714},[3860],{"type":50,"value":132},{"type":45,"tag":1587,"props":3862,"children":3863},{"style":1719},[3864],{"type":50,"value":3865},"optional",{"type":45,"tag":1587,"props":3867,"children":3868},{"style":1708},[3869],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3871,"children":3872},{"style":1714},[3873],{"type":50,"value":3874},",\n",{"type":45,"tag":1587,"props":3876,"children":3877},{"class":1589,"line":31},[3878,3883,3887,3891,3895,3899,3903,3907,3912,3916,3920,3924,3928],{"type":45,"tag":1587,"props":3879,"children":3880},{"style":1846},[3881],{"type":50,"value":3882},"  avatarUrl",{"type":45,"tag":1587,"props":3884,"children":3885},{"style":1714},[3886],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3888,"children":3889},{"style":1708},[3890],{"type":50,"value":3788},{"type":45,"tag":1587,"props":3892,"children":3893},{"style":1714},[3894],{"type":50,"value":132},{"type":45,"tag":1587,"props":3896,"children":3897},{"style":1719},[3898],{"type":50,"value":3830},{"type":45,"tag":1587,"props":3900,"children":3901},{"style":1708},[3902],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3904,"children":3905},{"style":1714},[3906],{"type":50,"value":132},{"type":45,"tag":1587,"props":3908,"children":3909},{"style":1719},[3910],{"type":50,"value":3911},"url",{"type":45,"tag":1587,"props":3913,"children":3914},{"style":1708},[3915],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3917,"children":3918},{"style":1714},[3919],{"type":50,"value":132},{"type":45,"tag":1587,"props":3921,"children":3922},{"style":1719},[3923],{"type":50,"value":3865},{"type":45,"tag":1587,"props":3925,"children":3926},{"style":1708},[3927],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3929,"children":3930},{"style":1714},[3931],{"type":50,"value":3874},{"type":45,"tag":1587,"props":3933,"children":3934},{"class":1589,"line":1617},[3935,3940,3944,3948,3952,3956,3960,3964,3968,3972],{"type":45,"tag":1587,"props":3936,"children":3937},{"style":1846},[3938],{"type":50,"value":3939},"  timezone",{"type":45,"tag":1587,"props":3941,"children":3942},{"style":1714},[3943],{"type":50,"value":1863},{"type":45,"tag":1587,"props":3945,"children":3946},{"style":1708},[3947],{"type":50,"value":3788},{"type":45,"tag":1587,"props":3949,"children":3950},{"style":1714},[3951],{"type":50,"value":132},{"type":45,"tag":1587,"props":3953,"children":3954},{"style":1719},[3955],{"type":50,"value":3830},{"type":45,"tag":1587,"props":3957,"children":3958},{"style":1708},[3959],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3961,"children":3962},{"style":1714},[3963],{"type":50,"value":132},{"type":45,"tag":1587,"props":3965,"children":3966},{"style":1719},[3967],{"type":50,"value":3865},{"type":45,"tag":1587,"props":3969,"children":3970},{"style":1708},[3971],{"type":50,"value":2539},{"type":45,"tag":1587,"props":3973,"children":3974},{"style":1714},[3975],{"type":50,"value":3874},{"type":45,"tag":1587,"props":3977,"children":3978},{"class":1589,"line":1626},[3979,3983,3987],{"type":45,"tag":1587,"props":3980,"children":3981},{"style":1714},[3982],{"type":50,"value":1959},{"type":45,"tag":1587,"props":3984,"children":3985},{"style":1708},[3986],{"type":50,"value":1786},{"type":45,"tag":1587,"props":3988,"children":3989},{"style":1714},[3990],{"type":50,"value":1918},{"type":45,"tag":1587,"props":3992,"children":3993},{"class":1589,"line":1635},[3994],{"type":45,"tag":1587,"props":3995,"children":3996},{"emptyLinePlaceholder":1611},[3997],{"type":50,"value":1614},{"type":45,"tag":1587,"props":3999,"children":4000},{"class":1589,"line":2301},[4001,4005,4009,4013,4017,4021,4025,4029,4033,4037,4041,4045,4049,4053,4057,4061,4065,4069],{"type":45,"tag":1587,"props":4002,"children":4003},{"style":1708},[4004],{"type":50,"value":1711},{"type":45,"tag":1587,"props":4006,"children":4007},{"style":1714},[4008],{"type":50,"value":132},{"type":45,"tag":1587,"props":4010,"children":4011},{"style":1719},[4012],{"type":50,"value":3500},{"type":45,"tag":1587,"props":4014,"children":4015},{"style":1708},[4016],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4018,"children":4019},{"style":1714},[4020],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4022,"children":4023},{"style":1735},[4024],{"type":50,"value":3513},{"type":45,"tag":1587,"props":4026,"children":4027},{"style":1714},[4028],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4030,"children":4031},{"style":1714},[4032],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4034,"children":4035},{"style":1708},[4036],{"type":50,"value":1752},{"type":45,"tag":1587,"props":4038,"children":4039},{"style":1714},[4040],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4042,"children":4043},{"style":1759},[4044],{"type":50,"value":1762},{"type":45,"tag":1587,"props":4046,"children":4047},{"style":1714},[4048],{"type":50,"value":1381},{"type":45,"tag":1587,"props":4050,"children":4051},{"style":1769},[4052],{"type":50,"value":1772},{"type":45,"tag":1587,"props":4054,"children":4055},{"style":1714},[4056],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4058,"children":4059},{"style":1769},[4060],{"type":50,"value":1781},{"type":45,"tag":1587,"props":4062,"children":4063},{"style":1714},[4064],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4066,"children":4067},{"style":1759},[4068],{"type":50,"value":1791},{"type":45,"tag":1587,"props":4070,"children":4071},{"style":1714},[4072],{"type":50,"value":1796},{"type":45,"tag":1587,"props":4074,"children":4075},{"class":1589,"line":2767},[4076,4080,4085,4089,4094,4098,4103,4107,4111,4115,4119,4123],{"type":45,"tag":1587,"props":4077,"children":4078},{"style":1759},[4079],{"type":50,"value":1804},{"type":45,"tag":1587,"props":4081,"children":4082},{"style":1708},[4083],{"type":50,"value":4084}," data",{"type":45,"tag":1587,"props":4086,"children":4087},{"style":1714},[4088],{"type":50,"value":1814},{"type":45,"tag":1587,"props":4090,"children":4091},{"style":1708},[4092],{"type":50,"value":4093}," ProfileUpdate",{"type":45,"tag":1587,"props":4095,"children":4096},{"style":1714},[4097],{"type":50,"value":132},{"type":45,"tag":1587,"props":4099,"children":4100},{"style":1719},[4101],{"type":50,"value":4102},"parse",{"type":45,"tag":1587,"props":4104,"children":4105},{"style":1846},[4106],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4108,"children":4109},{"style":1708},[4110],{"type":50,"value":1772},{"type":45,"tag":1587,"props":4112,"children":4113},{"style":1714},[4114],{"type":50,"value":132},{"type":45,"tag":1587,"props":4116,"children":4117},{"style":1708},[4118],{"type":50,"value":3681},{"type":45,"tag":1587,"props":4120,"children":4121},{"style":1846},[4122],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4124,"children":4125},{"style":1714},[4126],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4128,"children":4130},{"class":1589,"line":4129},9,[4131,4135,4139,4143,4147,4151,4155,4159,4163,4167,4171,4175,4179,4183,4187,4191,4195,4199,4203,4207,4211,4215,4220,4224,4228,4232],{"type":45,"tag":1587,"props":4132,"children":4133},{"style":1759},[4134],{"type":50,"value":1804},{"type":45,"tag":1587,"props":4136,"children":4137},{"style":1708},[4138],{"type":50,"value":3036},{"type":45,"tag":1587,"props":4140,"children":4141},{"style":1714},[4142],{"type":50,"value":1814},{"type":45,"tag":1587,"props":4144,"children":4145},{"style":1817},[4146],{"type":50,"value":1820},{"type":45,"tag":1587,"props":4148,"children":4149},{"style":1708},[4150],{"type":50,"value":1825},{"type":45,"tag":1587,"props":4152,"children":4153},{"style":1714},[4154],{"type":50,"value":132},{"type":45,"tag":1587,"props":4156,"children":4157},{"style":1708},[4158],{"type":50,"value":2176},{"type":45,"tag":1587,"props":4160,"children":4161},{"style":1714},[4162],{"type":50,"value":132},{"type":45,"tag":1587,"props":4164,"children":4165},{"style":1719},[4166],{"type":50,"value":3601},{"type":45,"tag":1587,"props":4168,"children":4169},{"style":1846},[4170],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4172,"children":4173},{"style":1714},[4174],{"type":50,"value":1853},{"type":45,"tag":1587,"props":4176,"children":4177},{"style":1846},[4178],{"type":50,"value":1858},{"type":45,"tag":1587,"props":4180,"children":4181},{"style":1714},[4182],{"type":50,"value":1863},{"type":45,"tag":1587,"props":4184,"children":4185},{"style":1714},[4186],{"type":50,"value":1868},{"type":45,"tag":1587,"props":4188,"children":4189},{"style":1846},[4190],{"type":50,"value":1873},{"type":45,"tag":1587,"props":4192,"children":4193},{"style":1714},[4194],{"type":50,"value":1863},{"type":45,"tag":1587,"props":4196,"children":4197},{"style":1708},[4198],{"type":50,"value":1882},{"type":45,"tag":1587,"props":4200,"children":4201},{"style":1714},[4202],{"type":50,"value":132},{"type":45,"tag":1587,"props":4204,"children":4205},{"style":1708},[4206],{"type":50,"value":2176},{"type":45,"tag":1587,"props":4208,"children":4209},{"style":1714},[4210],{"type":50,"value":132},{"type":45,"tag":1587,"props":4212,"children":4213},{"style":1708},[4214],{"type":50,"value":1900},{"type":45,"tag":1587,"props":4216,"children":4217},{"style":1714},[4218],{"type":50,"value":4219}," },",{"type":45,"tag":1587,"props":4221,"children":4222},{"style":1708},[4223],{"type":50,"value":4084},{"type":45,"tag":1587,"props":4225,"children":4226},{"style":1714},[4227],{"type":50,"value":1905},{"type":45,"tag":1587,"props":4229,"children":4230},{"style":1846},[4231],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4233,"children":4234},{"style":1714},[4235],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4237,"children":4239},{"class":1589,"line":4238},10,[4240,4244,4248,4252,4256,4260,4264],{"type":45,"tag":1587,"props":4241,"children":4242},{"style":1708},[4243],{"type":50,"value":1926},{"type":45,"tag":1587,"props":4245,"children":4246},{"style":1714},[4247],{"type":50,"value":132},{"type":45,"tag":1587,"props":4249,"children":4250},{"style":1719},[4251],{"type":50,"value":1935},{"type":45,"tag":1587,"props":4253,"children":4254},{"style":1846},[4255],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4257,"children":4258},{"style":1708},[4259],{"type":50,"value":2176},{"type":45,"tag":1587,"props":4261,"children":4262},{"style":1846},[4263],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4265,"children":4266},{"style":1714},[4267],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4269,"children":4271},{"class":1589,"line":4270},11,[4272,4276,4280],{"type":45,"tag":1587,"props":4273,"children":4274},{"style":1714},[4275],{"type":50,"value":1959},{"type":45,"tag":1587,"props":4277,"children":4278},{"style":1708},[4279],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4281,"children":4282},{"style":1714},[4283],{"type":50,"value":1918},{"type":45,"tag":1548,"props":4285,"children":4287},{"id":4286},"pattern-forged-token-grants-role-or-scope",[4288],{"type":50,"value":4289},"Pattern: Forged token grants role or scope",{"type":45,"tag":46,"props":4291,"children":4292},{},[4293,4295,4300],{"type":50,"value":4294},"Real incidents: jsonwebtoken CVE-2022-23540 (default-alg bypass), CVE-2022-23541 (RS→HS confusion), PyJWT CVE-2022-29217 (alg confusion), Java ECDSA CVE-2022-21449 (\"psychic signatures\"). See ",{"type":45,"tag":101,"props":4296,"children":4298},{"className":4297},[],[4299],{"type":50,"value":650},{"type":50,"value":132},{"type":45,"tag":46,"props":4302,"children":4303},{},[4304],{"type":45,"tag":66,"props":4305,"children":4306},{},[4307],{"type":50,"value":2340},{"type":45,"tag":1576,"props":4309,"children":4311},{"className":1578,"code":4310,"language":1580,"meta":1581,"style":1581},"payload = jwt.decode(token, options={\"verify_signature\": False})\nif payload[\"role\"] == \"admin\":\n    delete_user(request.data[\"user_id\"])\n# or\npayload = jwt.decode(token, key, algorithms=[\"HS256\", \"RS256\"])  # Mixed allows confusion.\nif \"org:admin\" in payload[\"scope\"]:\n    update_billing()\n",[4312],{"type":45,"tag":101,"props":4313,"children":4314},{"__ignoreMap":1581},[4315,4323,4331,4339,4347,4355,4363],{"type":45,"tag":1587,"props":4316,"children":4317},{"class":1589,"line":1590},[4318],{"type":45,"tag":1587,"props":4319,"children":4320},{},[4321],{"type":50,"value":4322},"payload = jwt.decode(token, options={\"verify_signature\": False})\n",{"type":45,"tag":1587,"props":4324,"children":4325},{"class":1589,"line":1599},[4326],{"type":45,"tag":1587,"props":4327,"children":4328},{},[4329],{"type":50,"value":4330},"if payload[\"role\"] == \"admin\":\n",{"type":45,"tag":1587,"props":4332,"children":4333},{"class":1589,"line":31},[4334],{"type":45,"tag":1587,"props":4335,"children":4336},{},[4337],{"type":50,"value":4338},"    delete_user(request.data[\"user_id\"])\n",{"type":45,"tag":1587,"props":4340,"children":4341},{"class":1589,"line":1617},[4342],{"type":45,"tag":1587,"props":4343,"children":4344},{},[4345],{"type":50,"value":4346},"# or\n",{"type":45,"tag":1587,"props":4348,"children":4349},{"class":1589,"line":1626},[4350],{"type":45,"tag":1587,"props":4351,"children":4352},{},[4353],{"type":50,"value":4354},"payload = jwt.decode(token, key, algorithms=[\"HS256\", \"RS256\"])  # Mixed allows confusion.\n",{"type":45,"tag":1587,"props":4356,"children":4357},{"class":1589,"line":1635},[4358],{"type":45,"tag":1587,"props":4359,"children":4360},{},[4361],{"type":50,"value":4362},"if \"org:admin\" in payload[\"scope\"]:\n",{"type":45,"tag":1587,"props":4364,"children":4365},{"class":1589,"line":2301},[4366],{"type":45,"tag":1587,"props":4367,"children":4368},{},[4369],{"type":50,"value":4370},"    update_billing()\n",{"type":45,"tag":46,"props":4372,"children":4373},{},[4374],{"type":45,"tag":66,"props":4375,"children":4376},{},[4377],{"type":50,"value":1654},{"type":45,"tag":1576,"props":4379,"children":4381},{"className":1578,"code":4380,"language":1580,"meta":1581,"style":1581},"payload = jwt.decode(token, key, algorithms=[\"RS256\"])\nif \"org:admin\" in payload[\"scope\"] and payload[\"org_id\"] == request.org.id:\n    update_billing()\n",[4382],{"type":45,"tag":101,"props":4383,"children":4384},{"__ignoreMap":1581},[4385,4393,4401],{"type":45,"tag":1587,"props":4386,"children":4387},{"class":1589,"line":1590},[4388],{"type":45,"tag":1587,"props":4389,"children":4390},{},[4391],{"type":50,"value":4392},"payload = jwt.decode(token, key, algorithms=[\"RS256\"])\n",{"type":45,"tag":1587,"props":4394,"children":4395},{"class":1589,"line":1599},[4396],{"type":45,"tag":1587,"props":4397,"children":4398},{},[4399],{"type":50,"value":4400},"if \"org:admin\" in payload[\"scope\"] and payload[\"org_id\"] == request.org.id:\n",{"type":45,"tag":1587,"props":4402,"children":4403},{"class":1589,"line":31},[4404],{"type":45,"tag":1587,"props":4405,"children":4406},{},[4407],{"type":50,"value":4370},{"type":45,"tag":46,"props":4409,"children":4410},{},[4411],{"type":45,"tag":66,"props":4412,"children":4413},{},[4414],{"type":50,"value":2838},{"type":45,"tag":1576,"props":4416,"children":4418},{"className":1696,"code":4417,"language":1698,"meta":1581,"style":1581},"const claims = jwt.decode(token);           \u002F\u002F Returns claims without verifying.\nif (claims.role === 'admin') await deleteUser(req.body.userId);\n\nconst claims = jwt.verify(token, key);      \u002F\u002F CVE-2022-23540: no algorithms pin.\nif (claims.scope?.includes('org:admin')) await updateBilling();\n",[4419],{"type":45,"tag":101,"props":4420,"children":4421},{"__ignoreMap":1581},[4422,4466,4545,4552,4603],{"type":45,"tag":1587,"props":4423,"children":4424},{"class":1589,"line":1590},[4425,4429,4434,4438,4443,4447,4452,4457,4461],{"type":45,"tag":1587,"props":4426,"children":4427},{"style":1759},[4428],{"type":50,"value":3773},{"type":45,"tag":1587,"props":4430,"children":4431},{"style":1708},[4432],{"type":50,"value":4433}," claims ",{"type":45,"tag":1587,"props":4435,"children":4436},{"style":1714},[4437],{"type":50,"value":3783},{"type":45,"tag":1587,"props":4439,"children":4440},{"style":1708},[4441],{"type":50,"value":4442}," jwt",{"type":45,"tag":1587,"props":4444,"children":4445},{"style":1714},[4446],{"type":50,"value":132},{"type":45,"tag":1587,"props":4448,"children":4449},{"style":1719},[4450],{"type":50,"value":4451},"decode",{"type":45,"tag":1587,"props":4453,"children":4454},{"style":1708},[4455],{"type":50,"value":4456},"(token)",{"type":45,"tag":1587,"props":4458,"children":4459},{"style":1714},[4460],{"type":50,"value":3102},{"type":45,"tag":1587,"props":4462,"children":4463},{"style":3105},[4464],{"type":50,"value":4465},"           \u002F\u002F Returns claims without verifying.\n",{"type":45,"tag":1587,"props":4467,"children":4468},{"class":1589,"line":1599},[4469,4474,4479,4483,4488,4493,4497,4501,4505,4509,4514,4519,4524,4528,4532,4536,4541],{"type":45,"tag":1587,"props":4470,"children":4471},{"style":1817},[4472],{"type":50,"value":4473},"if",{"type":45,"tag":1587,"props":4475,"children":4476},{"style":1708},[4477],{"type":50,"value":4478}," (claims",{"type":45,"tag":1587,"props":4480,"children":4481},{"style":1714},[4482],{"type":50,"value":132},{"type":45,"tag":1587,"props":4484,"children":4485},{"style":1708},[4486],{"type":50,"value":4487},"role ",{"type":45,"tag":1587,"props":4489,"children":4490},{"style":1714},[4491],{"type":50,"value":4492},"===",{"type":45,"tag":1587,"props":4494,"children":4495},{"style":1714},[4496],{"type":50,"value":2942},{"type":45,"tag":1587,"props":4498,"children":4499},{"style":1735},[4500],{"type":50,"value":2947},{"type":45,"tag":1587,"props":4502,"children":4503},{"style":1714},[4504],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4506,"children":4507},{"style":1708},[4508],{"type":50,"value":2231},{"type":45,"tag":1587,"props":4510,"children":4511},{"style":1817},[4512],{"type":50,"value":4513},"await",{"type":45,"tag":1587,"props":4515,"children":4516},{"style":1719},[4517],{"type":50,"value":4518}," deleteUser",{"type":45,"tag":1587,"props":4520,"children":4521},{"style":1708},[4522],{"type":50,"value":4523},"(req",{"type":45,"tag":1587,"props":4525,"children":4526},{"style":1714},[4527],{"type":50,"value":132},{"type":45,"tag":1587,"props":4529,"children":4530},{"style":1708},[4531],{"type":50,"value":3681},{"type":45,"tag":1587,"props":4533,"children":4534},{"style":1714},[4535],{"type":50,"value":132},{"type":45,"tag":1587,"props":4537,"children":4538},{"style":1708},[4539],{"type":50,"value":4540},"userId)",{"type":45,"tag":1587,"props":4542,"children":4543},{"style":1714},[4544],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4546,"children":4547},{"class":1589,"line":31},[4548],{"type":45,"tag":1587,"props":4549,"children":4550},{"emptyLinePlaceholder":1611},[4551],{"type":50,"value":1614},{"type":45,"tag":1587,"props":4553,"children":4554},{"class":1589,"line":1617},[4555,4559,4563,4567,4571,4575,4580,4585,4589,4594,4598],{"type":45,"tag":1587,"props":4556,"children":4557},{"style":1759},[4558],{"type":50,"value":3773},{"type":45,"tag":1587,"props":4560,"children":4561},{"style":1708},[4562],{"type":50,"value":4433},{"type":45,"tag":1587,"props":4564,"children":4565},{"style":1714},[4566],{"type":50,"value":3783},{"type":45,"tag":1587,"props":4568,"children":4569},{"style":1708},[4570],{"type":50,"value":4442},{"type":45,"tag":1587,"props":4572,"children":4573},{"style":1714},[4574],{"type":50,"value":132},{"type":45,"tag":1587,"props":4576,"children":4577},{"style":1719},[4578],{"type":50,"value":4579},"verify",{"type":45,"tag":1587,"props":4581,"children":4582},{"style":1708},[4583],{"type":50,"value":4584},"(token",{"type":45,"tag":1587,"props":4586,"children":4587},{"style":1714},[4588],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4590,"children":4591},{"style":1708},[4592],{"type":50,"value":4593}," key)",{"type":45,"tag":1587,"props":4595,"children":4596},{"style":1714},[4597],{"type":50,"value":3102},{"type":45,"tag":1587,"props":4599,"children":4600},{"style":3105},[4601],{"type":50,"value":4602},"      \u002F\u002F CVE-2022-23540: no algorithms pin.\n",{"type":45,"tag":1587,"props":4604,"children":4605},{"class":1589,"line":1626},[4606,4610,4614,4618,4623,4628,4633,4637,4641,4646,4650,4655,4659,4664,4668],{"type":45,"tag":1587,"props":4607,"children":4608},{"style":1817},[4609],{"type":50,"value":4473},{"type":45,"tag":1587,"props":4611,"children":4612},{"style":1708},[4613],{"type":50,"value":4478},{"type":45,"tag":1587,"props":4615,"children":4616},{"style":1714},[4617],{"type":50,"value":132},{"type":45,"tag":1587,"props":4619,"children":4620},{"style":1708},[4621],{"type":50,"value":4622},"scope",{"type":45,"tag":1587,"props":4624,"children":4625},{"style":1714},[4626],{"type":50,"value":4627},"?.",{"type":45,"tag":1587,"props":4629,"children":4630},{"style":1719},[4631],{"type":50,"value":4632},"includes",{"type":45,"tag":1587,"props":4634,"children":4635},{"style":1708},[4636],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4638,"children":4639},{"style":1714},[4640],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4642,"children":4643},{"style":1735},[4644],{"type":50,"value":4645},"org:admin",{"type":45,"tag":1587,"props":4647,"children":4648},{"style":1714},[4649],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4651,"children":4652},{"style":1708},[4653],{"type":50,"value":4654},")) ",{"type":45,"tag":1587,"props":4656,"children":4657},{"style":1817},[4658],{"type":50,"value":4513},{"type":45,"tag":1587,"props":4660,"children":4661},{"style":1719},[4662],{"type":50,"value":4663}," updateBilling",{"type":45,"tag":1587,"props":4665,"children":4666},{"style":1708},[4667],{"type":50,"value":2539},{"type":45,"tag":1587,"props":4669,"children":4670},{"style":1714},[4671],{"type":50,"value":1918},{"type":45,"tag":46,"props":4673,"children":4674},{},[4675],{"type":45,"tag":66,"props":4676,"children":4677},{},[4678],{"type":50,"value":1975},{"type":45,"tag":1576,"props":4680,"children":4682},{"className":1696,"code":4681,"language":1698,"meta":1581,"style":1581},"const claims = jwt.verify(token, publicKey, { algorithms: ['RS256'] });\nif (claims.scope?.includes('org:admin') && claims.orgId === req.org.id) {\n  await updateBilling();\n}\n",[4683],{"type":45,"tag":101,"props":4684,"children":4685},{"__ignoreMap":1581},[4686,4778,4874,4894],{"type":45,"tag":1587,"props":4687,"children":4688},{"class":1589,"line":1590},[4689,4693,4697,4701,4705,4709,4713,4717,4721,4726,4730,4734,4739,4743,4748,4752,4757,4761,4766,4770,4774],{"type":45,"tag":1587,"props":4690,"children":4691},{"style":1759},[4692],{"type":50,"value":3773},{"type":45,"tag":1587,"props":4694,"children":4695},{"style":1708},[4696],{"type":50,"value":4433},{"type":45,"tag":1587,"props":4698,"children":4699},{"style":1714},[4700],{"type":50,"value":3783},{"type":45,"tag":1587,"props":4702,"children":4703},{"style":1708},[4704],{"type":50,"value":4442},{"type":45,"tag":1587,"props":4706,"children":4707},{"style":1714},[4708],{"type":50,"value":132},{"type":45,"tag":1587,"props":4710,"children":4711},{"style":1719},[4712],{"type":50,"value":4579},{"type":45,"tag":1587,"props":4714,"children":4715},{"style":1708},[4716],{"type":50,"value":4584},{"type":45,"tag":1587,"props":4718,"children":4719},{"style":1714},[4720],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4722,"children":4723},{"style":1708},[4724],{"type":50,"value":4725}," publicKey",{"type":45,"tag":1587,"props":4727,"children":4728},{"style":1714},[4729],{"type":50,"value":1747},{"type":45,"tag":1587,"props":4731,"children":4732},{"style":1714},[4733],{"type":50,"value":1868},{"type":45,"tag":1587,"props":4735,"children":4736},{"style":1846},[4737],{"type":50,"value":4738}," algorithms",{"type":45,"tag":1587,"props":4740,"children":4741},{"style":1714},[4742],{"type":50,"value":1863},{"type":45,"tag":1587,"props":4744,"children":4745},{"style":1708},[4746],{"type":50,"value":4747}," [",{"type":45,"tag":1587,"props":4749,"children":4750},{"style":1714},[4751],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4753,"children":4754},{"style":1735},[4755],{"type":50,"value":4756},"RS256",{"type":45,"tag":1587,"props":4758,"children":4759},{"style":1714},[4760],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4762,"children":4763},{"style":1708},[4764],{"type":50,"value":4765},"] ",{"type":45,"tag":1587,"props":4767,"children":4768},{"style":1714},[4769],{"type":50,"value":1959},{"type":45,"tag":1587,"props":4771,"children":4772},{"style":1708},[4773],{"type":50,"value":1786},{"type":45,"tag":1587,"props":4775,"children":4776},{"style":1714},[4777],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4779,"children":4780},{"class":1589,"line":1599},[4781,4785,4789,4793,4797,4801,4805,4809,4813,4817,4821,4825,4830,4835,4839,4844,4848,4852,4856,4861,4865,4870],{"type":45,"tag":1587,"props":4782,"children":4783},{"style":1817},[4784],{"type":50,"value":4473},{"type":45,"tag":1587,"props":4786,"children":4787},{"style":1708},[4788],{"type":50,"value":4478},{"type":45,"tag":1587,"props":4790,"children":4791},{"style":1714},[4792],{"type":50,"value":132},{"type":45,"tag":1587,"props":4794,"children":4795},{"style":1708},[4796],{"type":50,"value":4622},{"type":45,"tag":1587,"props":4798,"children":4799},{"style":1714},[4800],{"type":50,"value":4627},{"type":45,"tag":1587,"props":4802,"children":4803},{"style":1719},[4804],{"type":50,"value":4632},{"type":45,"tag":1587,"props":4806,"children":4807},{"style":1708},[4808],{"type":50,"value":1727},{"type":45,"tag":1587,"props":4810,"children":4811},{"style":1714},[4812],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4814,"children":4815},{"style":1735},[4816],{"type":50,"value":4645},{"type":45,"tag":1587,"props":4818,"children":4819},{"style":1714},[4820],{"type":50,"value":1732},{"type":45,"tag":1587,"props":4822,"children":4823},{"style":1708},[4824],{"type":50,"value":2231},{"type":45,"tag":1587,"props":4826,"children":4827},{"style":1714},[4828],{"type":50,"value":4829},"&&",{"type":45,"tag":1587,"props":4831,"children":4832},{"style":1708},[4833],{"type":50,"value":4834}," claims",{"type":45,"tag":1587,"props":4836,"children":4837},{"style":1714},[4838],{"type":50,"value":132},{"type":45,"tag":1587,"props":4840,"children":4841},{"style":1708},[4842],{"type":50,"value":4843},"orgId ",{"type":45,"tag":1587,"props":4845,"children":4846},{"style":1714},[4847],{"type":50,"value":4492},{"type":45,"tag":1587,"props":4849,"children":4850},{"style":1708},[4851],{"type":50,"value":1882},{"type":45,"tag":1587,"props":4853,"children":4854},{"style":1714},[4855],{"type":50,"value":132},{"type":45,"tag":1587,"props":4857,"children":4858},{"style":1708},[4859],{"type":50,"value":4860},"org",{"type":45,"tag":1587,"props":4862,"children":4863},{"style":1714},[4864],{"type":50,"value":132},{"type":45,"tag":1587,"props":4866,"children":4867},{"style":1708},[4868],{"type":50,"value":4869},"id) ",{"type":45,"tag":1587,"props":4871,"children":4872},{"style":1714},[4873],{"type":50,"value":2106},{"type":45,"tag":1587,"props":4875,"children":4876},{"class":1589,"line":31},[4877,4882,4886,4890],{"type":45,"tag":1587,"props":4878,"children":4879},{"style":1817},[4880],{"type":50,"value":4881},"  await",{"type":45,"tag":1587,"props":4883,"children":4884},{"style":1719},[4885],{"type":50,"value":4663},{"type":45,"tag":1587,"props":4887,"children":4888},{"style":1846},[4889],{"type":50,"value":2539},{"type":45,"tag":1587,"props":4891,"children":4892},{"style":1714},[4893],{"type":50,"value":1918},{"type":45,"tag":1587,"props":4895,"children":4896},{"class":1589,"line":1617},[4897],{"type":45,"tag":1587,"props":4898,"children":4899},{"style":1714},[4900],{"type":50,"value":2551},{"type":45,"tag":1548,"props":4902,"children":4904},{"id":4903},"pattern-authorization-guard-declared-but-not-applied",[4905],{"type":50,"value":4906},"Pattern: Authorization guard declared but not applied",{"type":45,"tag":46,"props":4908,"children":4909},{},[4910,4912,4918],{"type":50,"value":4911},"Real shape from a parallel research scan: MLflow ajax-api endpoints shipped without the shared ",{"type":45,"tag":101,"props":4913,"children":4915},{"className":4914},[],[4916],{"type":50,"value":4917},"Depends()",{"type":50,"value":132},{"type":45,"tag":46,"props":4920,"children":4921},{},[4922],{"type":45,"tag":66,"props":4923,"children":4924},{},[4925],{"type":50,"value":4926},"Python (FastAPI) - bad:",{"type":45,"tag":1576,"props":4928,"children":4930},{"className":1578,"code":4929,"language":1580,"meta":1581,"style":1581},"# Dependency is defined...\nasync def require_admin(user: User = Depends(require_user)) -> User: ...\n\n# ...but this router never references it.\nadmin_router = APIRouter(prefix=\"\u002Fadmin\")\n\n@admin_router.get(\"\u002Fusers\")\nasync def list_users():\n    return await db.users.find_all()\n",[4931],{"type":45,"tag":101,"props":4932,"children":4933},{"__ignoreMap":1581},[4934,4942,4950,4957,4965,4973,4980,4988,4996],{"type":45,"tag":1587,"props":4935,"children":4936},{"class":1589,"line":1590},[4937],{"type":45,"tag":1587,"props":4938,"children":4939},{},[4940],{"type":50,"value":4941},"# Dependency is defined...\n",{"type":45,"tag":1587,"props":4943,"children":4944},{"class":1589,"line":1599},[4945],{"type":45,"tag":1587,"props":4946,"children":4947},{},[4948],{"type":50,"value":4949},"async def require_admin(user: User = Depends(require_user)) -> User: ...\n",{"type":45,"tag":1587,"props":4951,"children":4952},{"class":1589,"line":31},[4953],{"type":45,"tag":1587,"props":4954,"children":4955},{"emptyLinePlaceholder":1611},[4956],{"type":50,"value":1614},{"type":45,"tag":1587,"props":4958,"children":4959},{"class":1589,"line":1617},[4960],{"type":45,"tag":1587,"props":4961,"children":4962},{},[4963],{"type":50,"value":4964},"# ...but this router never references it.\n",{"type":45,"tag":1587,"props":4966,"children":4967},{"class":1589,"line":1626},[4968],{"type":45,"tag":1587,"props":4969,"children":4970},{},[4971],{"type":50,"value":4972},"admin_router = APIRouter(prefix=\"\u002Fadmin\")\n",{"type":45,"tag":1587,"props":4974,"children":4975},{"class":1589,"line":1635},[4976],{"type":45,"tag":1587,"props":4977,"children":4978},{"emptyLinePlaceholder":1611},[4979],{"type":50,"value":1614},{"type":45,"tag":1587,"props":4981,"children":4982},{"class":1589,"line":2301},[4983],{"type":45,"tag":1587,"props":4984,"children":4985},{},[4986],{"type":50,"value":4987},"@admin_router.get(\"\u002Fusers\")\n",{"type":45,"tag":1587,"props":4989,"children":4990},{"class":1589,"line":2767},[4991],{"type":45,"tag":1587,"props":4992,"children":4993},{},[4994],{"type":50,"value":4995},"async def list_users():\n",{"type":45,"tag":1587,"props":4997,"children":4998},{"class":1589,"line":4129},[4999],{"type":45,"tag":1587,"props":5000,"children":5001},{},[5002],{"type":50,"value":5003},"    return await db.users.find_all()\n",{"type":45,"tag":46,"props":5005,"children":5006},{},[5007],{"type":45,"tag":66,"props":5008,"children":5009},{},[5010],{"type":50,"value":1654},{"type":45,"tag":1576,"props":5012,"children":5014},{"className":1578,"code":5013,"language":1580,"meta":1581,"style":1581},"admin_router = APIRouter(prefix=\"\u002Fadmin\", dependencies=[Depends(require_admin)])\n\n@admin_router.get(\"\u002Fusers\")\nasync def list_users():\n    return await db.users.find_all()\n",[5015],{"type":45,"tag":101,"props":5016,"children":5017},{"__ignoreMap":1581},[5018,5026,5033,5040,5047],{"type":45,"tag":1587,"props":5019,"children":5020},{"class":1589,"line":1590},[5021],{"type":45,"tag":1587,"props":5022,"children":5023},{},[5024],{"type":50,"value":5025},"admin_router = APIRouter(prefix=\"\u002Fadmin\", dependencies=[Depends(require_admin)])\n",{"type":45,"tag":1587,"props":5027,"children":5028},{"class":1589,"line":1599},[5029],{"type":45,"tag":1587,"props":5030,"children":5031},{"emptyLinePlaceholder":1611},[5032],{"type":50,"value":1614},{"type":45,"tag":1587,"props":5034,"children":5035},{"class":1589,"line":31},[5036],{"type":45,"tag":1587,"props":5037,"children":5038},{},[5039],{"type":50,"value":4987},{"type":45,"tag":1587,"props":5041,"children":5042},{"class":1589,"line":1617},[5043],{"type":45,"tag":1587,"props":5044,"children":5045},{},[5046],{"type":50,"value":4995},{"type":45,"tag":1587,"props":5048,"children":5049},{"class":1589,"line":1626},[5050],{"type":45,"tag":1587,"props":5051,"children":5052},{},[5053],{"type":50,"value":5003},{"type":45,"tag":46,"props":5055,"children":5056},{},[5057],{"type":45,"tag":66,"props":5058,"children":5059},{},[5060],{"type":50,"value":5061},"TypeScript (Express) - bad:",{"type":45,"tag":1576,"props":5063,"children":5065},{"className":1696,"code":5064,"language":1698,"meta":1581,"style":1581},"app.use('\u002Fapi', requireAuth);\napp.use('\u002Fadmin', requireAuth, adminRouter);  \u002F\u002F No requireAdmin gate.\n",[5066],{"type":45,"tag":101,"props":5067,"children":5068},{"__ignoreMap":1581},[5069,5116],{"type":45,"tag":1587,"props":5070,"children":5071},{"class":1589,"line":1590},[5072,5077,5081,5086,5090,5094,5099,5103,5107,5112],{"type":45,"tag":1587,"props":5073,"children":5074},{"style":1708},[5075],{"type":50,"value":5076},"app",{"type":45,"tag":1587,"props":5078,"children":5079},{"style":1714},[5080],{"type":50,"value":132},{"type":45,"tag":1587,"props":5082,"children":5083},{"style":1719},[5084],{"type":50,"value":5085},"use",{"type":45,"tag":1587,"props":5087,"children":5088},{"style":1708},[5089],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5091,"children":5092},{"style":1714},[5093],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5095,"children":5096},{"style":1735},[5097],{"type":50,"value":5098},"\u002Fapi",{"type":45,"tag":1587,"props":5100,"children":5101},{"style":1714},[5102],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5104,"children":5105},{"style":1714},[5106],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5108,"children":5109},{"style":1708},[5110],{"type":50,"value":5111}," requireAuth)",{"type":45,"tag":1587,"props":5113,"children":5114},{"style":1714},[5115],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5117,"children":5118},{"class":1589,"line":1599},[5119,5123,5127,5131,5135,5139,5144,5148,5152,5156,5160,5165,5169],{"type":45,"tag":1587,"props":5120,"children":5121},{"style":1708},[5122],{"type":50,"value":5076},{"type":45,"tag":1587,"props":5124,"children":5125},{"style":1714},[5126],{"type":50,"value":132},{"type":45,"tag":1587,"props":5128,"children":5129},{"style":1719},[5130],{"type":50,"value":5085},{"type":45,"tag":1587,"props":5132,"children":5133},{"style":1708},[5134],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5136,"children":5137},{"style":1714},[5138],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5140,"children":5141},{"style":1735},[5142],{"type":50,"value":5143},"\u002Fadmin",{"type":45,"tag":1587,"props":5145,"children":5146},{"style":1714},[5147],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5149,"children":5150},{"style":1714},[5151],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5153,"children":5154},{"style":1708},[5155],{"type":50,"value":1752},{"type":45,"tag":1587,"props":5157,"children":5158},{"style":1714},[5159],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5161,"children":5162},{"style":1708},[5163],{"type":50,"value":5164}," adminRouter)",{"type":45,"tag":1587,"props":5166,"children":5167},{"style":1714},[5168],{"type":50,"value":3102},{"type":45,"tag":1587,"props":5170,"children":5171},{"style":3105},[5172],{"type":50,"value":5173},"  \u002F\u002F No requireAdmin gate.\n",{"type":45,"tag":46,"props":5175,"children":5176},{},[5177],{"type":45,"tag":66,"props":5178,"children":5179},{},[5180],{"type":50,"value":1975},{"type":45,"tag":1576,"props":5182,"children":5184},{"className":1696,"code":5183,"language":1698,"meta":1581,"style":1581},"app.use('\u002Fapi', requireAuth);\napp.use('\u002Fadmin', requireAuth, requireAdmin, adminRouter);\n",[5185],{"type":45,"tag":101,"props":5186,"children":5187},{"__ignoreMap":1581},[5188,5231],{"type":45,"tag":1587,"props":5189,"children":5190},{"class":1589,"line":1590},[5191,5195,5199,5203,5207,5211,5215,5219,5223,5227],{"type":45,"tag":1587,"props":5192,"children":5193},{"style":1708},[5194],{"type":50,"value":5076},{"type":45,"tag":1587,"props":5196,"children":5197},{"style":1714},[5198],{"type":50,"value":132},{"type":45,"tag":1587,"props":5200,"children":5201},{"style":1719},[5202],{"type":50,"value":5085},{"type":45,"tag":1587,"props":5204,"children":5205},{"style":1708},[5206],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5208,"children":5209},{"style":1714},[5210],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5212,"children":5213},{"style":1735},[5214],{"type":50,"value":5098},{"type":45,"tag":1587,"props":5216,"children":5217},{"style":1714},[5218],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5220,"children":5221},{"style":1714},[5222],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5224,"children":5225},{"style":1708},[5226],{"type":50,"value":5111},{"type":45,"tag":1587,"props":5228,"children":5229},{"style":1714},[5230],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5232,"children":5233},{"class":1589,"line":1599},[5234,5238,5242,5246,5250,5254,5258,5262,5266,5270,5274,5279,5283,5287],{"type":45,"tag":1587,"props":5235,"children":5236},{"style":1708},[5237],{"type":50,"value":5076},{"type":45,"tag":1587,"props":5239,"children":5240},{"style":1714},[5241],{"type":50,"value":132},{"type":45,"tag":1587,"props":5243,"children":5244},{"style":1719},[5245],{"type":50,"value":5085},{"type":45,"tag":1587,"props":5247,"children":5248},{"style":1708},[5249],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5251,"children":5252},{"style":1714},[5253],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5255,"children":5256},{"style":1735},[5257],{"type":50,"value":5143},{"type":45,"tag":1587,"props":5259,"children":5260},{"style":1714},[5261],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5263,"children":5264},{"style":1714},[5265],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5267,"children":5268},{"style":1708},[5269],{"type":50,"value":1752},{"type":45,"tag":1587,"props":5271,"children":5272},{"style":1714},[5273],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5275,"children":5276},{"style":1708},[5277],{"type":50,"value":5278}," requireAdmin",{"type":45,"tag":1587,"props":5280,"children":5281},{"style":1714},[5282],{"type":50,"value":1747},{"type":45,"tag":1587,"props":5284,"children":5285},{"style":1708},[5286],{"type":50,"value":5164},{"type":45,"tag":1587,"props":5288,"children":5289},{"style":1714},[5290],{"type":50,"value":1918},{"type":45,"tag":1548,"props":5292,"children":5294},{"id":5293},"pattern-nextjs-server-action-without-in-action-auth",[5295],{"type":50,"value":5296},"Pattern: Next.js Server Action without in-action auth",{"type":45,"tag":46,"props":5298,"children":5299},{},[5300,5302,5307],{"type":50,"value":5301},"Real incident: CVE-2025-55182 (React2Shell) — Next.js Server Actions re-exposed handlers; data-security docs explicitly require re-auth in every action. See ",{"type":45,"tag":101,"props":5303,"children":5305},{"className":5304},[],[5306],{"type":50,"value":599},{"type":50,"value":132},{"type":45,"tag":46,"props":5309,"children":5310},{},[5311],{"type":45,"tag":66,"props":5312,"children":5313},{},[5314],{"type":50,"value":2838},{"type":45,"tag":1576,"props":5316,"children":5318},{"className":1696,"code":5317,"language":1698,"meta":1581,"style":1581},"\u002F\u002F app\u002Fadmin\u002Fpage.tsx\nexport default async function AdminPage() {\n  const session = await auth();\n  if (!session?.user?.isAdmin) redirect('\u002F');\n  return \u003CAdminForm \u002F>;\n}\n\n\u002F\u002F app\u002Fadmin\u002Factions.ts\n'use server';\nexport async function deleteUser(userId: string) {\n  await db.user.delete({ where: { id: userId } });\n  \u002F\u002F No auth check. The server action is invokable by anyone who can POST to it.\n}\n",[5319],{"type":45,"tag":101,"props":5320,"children":5321},{"__ignoreMap":1581},[5322,5330,5365,5398,5469,5495,5502,5509,5517,5537,5582,5658,5667],{"type":45,"tag":1587,"props":5323,"children":5324},{"class":1589,"line":1590},[5325],{"type":45,"tag":1587,"props":5326,"children":5327},{"style":3105},[5328],{"type":50,"value":5329},"\u002F\u002F app\u002Fadmin\u002Fpage.tsx\n",{"type":45,"tag":1587,"props":5331,"children":5332},{"class":1589,"line":1599},[5333,5338,5343,5347,5352,5357,5361],{"type":45,"tag":1587,"props":5334,"children":5335},{"style":1817},[5336],{"type":50,"value":5337},"export",{"type":45,"tag":1587,"props":5339,"children":5340},{"style":1817},[5341],{"type":50,"value":5342}," default",{"type":45,"tag":1587,"props":5344,"children":5345},{"style":1759},[5346],{"type":50,"value":1762},{"type":45,"tag":1587,"props":5348,"children":5349},{"style":1759},[5350],{"type":50,"value":5351}," function",{"type":45,"tag":1587,"props":5353,"children":5354},{"style":1719},[5355],{"type":50,"value":5356}," AdminPage",{"type":45,"tag":1587,"props":5358,"children":5359},{"style":1714},[5360],{"type":50,"value":2539},{"type":45,"tag":1587,"props":5362,"children":5363},{"style":1714},[5364],{"type":50,"value":1796},{"type":45,"tag":1587,"props":5366,"children":5367},{"class":1589,"line":31},[5368,5372,5377,5381,5385,5390,5394],{"type":45,"tag":1587,"props":5369,"children":5370},{"style":1759},[5371],{"type":50,"value":1804},{"type":45,"tag":1587,"props":5373,"children":5374},{"style":1708},[5375],{"type":50,"value":5376}," session",{"type":45,"tag":1587,"props":5378,"children":5379},{"style":1714},[5380],{"type":50,"value":1814},{"type":45,"tag":1587,"props":5382,"children":5383},{"style":1817},[5384],{"type":50,"value":1820},{"type":45,"tag":1587,"props":5386,"children":5387},{"style":1719},[5388],{"type":50,"value":5389}," auth",{"type":45,"tag":1587,"props":5391,"children":5392},{"style":1846},[5393],{"type":50,"value":2539},{"type":45,"tag":1587,"props":5395,"children":5396},{"style":1714},[5397],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5399,"children":5400},{"class":1589,"line":1617},[5401,5405,5409,5413,5418,5422,5426,5430,5435,5439,5444,5448,5452,5457,5461,5465],{"type":45,"tag":1587,"props":5402,"children":5403},{"style":1817},[5404],{"type":50,"value":2213},{"type":45,"tag":1587,"props":5406,"children":5407},{"style":1846},[5408],{"type":50,"value":1381},{"type":45,"tag":1587,"props":5410,"children":5411},{"style":1714},[5412],{"type":50,"value":2222},{"type":45,"tag":1587,"props":5414,"children":5415},{"style":1708},[5416],{"type":50,"value":5417},"session",{"type":45,"tag":1587,"props":5419,"children":5420},{"style":1714},[5421],{"type":50,"value":4627},{"type":45,"tag":1587,"props":5423,"children":5424},{"style":1708},[5425],{"type":50,"value":2176},{"type":45,"tag":1587,"props":5427,"children":5428},{"style":1714},[5429],{"type":50,"value":4627},{"type":45,"tag":1587,"props":5431,"children":5432},{"style":1708},[5433],{"type":50,"value":5434},"isAdmin",{"type":45,"tag":1587,"props":5436,"children":5437},{"style":1846},[5438],{"type":50,"value":2231},{"type":45,"tag":1587,"props":5440,"children":5441},{"style":1719},[5442],{"type":50,"value":5443},"redirect",{"type":45,"tag":1587,"props":5445,"children":5446},{"style":1846},[5447],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5449,"children":5450},{"style":1714},[5451],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5453,"children":5454},{"style":1735},[5455],{"type":50,"value":5456},"\u002F",{"type":45,"tag":1587,"props":5458,"children":5459},{"style":1714},[5460],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5462,"children":5463},{"style":1846},[5464],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5466,"children":5467},{"style":1714},[5468],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5470,"children":5471},{"class":1589,"line":1626},[5472,5476,5481,5486,5491],{"type":45,"tag":1587,"props":5473,"children":5474},{"style":1817},[5475],{"type":50,"value":2516},{"type":45,"tag":1587,"props":5477,"children":5478},{"style":1846},[5479],{"type":50,"value":5480}," \u003C",{"type":45,"tag":1587,"props":5482,"children":5483},{"style":2873},[5484],{"type":50,"value":5485},"AdminForm",{"type":45,"tag":1587,"props":5487,"children":5488},{"style":1846},[5489],{"type":50,"value":5490}," \u002F>",{"type":45,"tag":1587,"props":5492,"children":5493},{"style":1714},[5494],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5496,"children":5497},{"class":1589,"line":1635},[5498],{"type":45,"tag":1587,"props":5499,"children":5500},{"style":1714},[5501],{"type":50,"value":2551},{"type":45,"tag":1587,"props":5503,"children":5504},{"class":1589,"line":2301},[5505],{"type":45,"tag":1587,"props":5506,"children":5507},{"emptyLinePlaceholder":1611},[5508],{"type":50,"value":1614},{"type":45,"tag":1587,"props":5510,"children":5511},{"class":1589,"line":2767},[5512],{"type":45,"tag":1587,"props":5513,"children":5514},{"style":3105},[5515],{"type":50,"value":5516},"\u002F\u002F app\u002Fadmin\u002Factions.ts\n",{"type":45,"tag":1587,"props":5518,"children":5519},{"class":1589,"line":4129},[5520,5524,5529,5533],{"type":45,"tag":1587,"props":5521,"children":5522},{"style":1714},[5523],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5525,"children":5526},{"style":1735},[5527],{"type":50,"value":5528},"use server",{"type":45,"tag":1587,"props":5530,"children":5531},{"style":1714},[5532],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5534,"children":5535},{"style":1714},[5536],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5538,"children":5539},{"class":1589,"line":4238},[5540,5544,5548,5552,5556,5560,5565,5569,5574,5578],{"type":45,"tag":1587,"props":5541,"children":5542},{"style":1817},[5543],{"type":50,"value":5337},{"type":45,"tag":1587,"props":5545,"children":5546},{"style":1759},[5547],{"type":50,"value":1762},{"type":45,"tag":1587,"props":5549,"children":5550},{"style":1759},[5551],{"type":50,"value":5351},{"type":45,"tag":1587,"props":5553,"children":5554},{"style":1719},[5555],{"type":50,"value":4518},{"type":45,"tag":1587,"props":5557,"children":5558},{"style":1714},[5559],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5561,"children":5562},{"style":1769},[5563],{"type":50,"value":5564},"userId",{"type":45,"tag":1587,"props":5566,"children":5567},{"style":1714},[5568],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5570,"children":5571},{"style":2873},[5572],{"type":50,"value":5573}," string",{"type":45,"tag":1587,"props":5575,"children":5576},{"style":1714},[5577],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5579,"children":5580},{"style":1714},[5581],{"type":50,"value":1796},{"type":45,"tag":1587,"props":5583,"children":5584},{"class":1589,"line":4270},[5585,5589,5593,5597,5601,5605,5610,5614,5618,5622,5626,5630,5634,5638,5642,5646,5650,5654],{"type":45,"tag":1587,"props":5586,"children":5587},{"style":1817},[5588],{"type":50,"value":4881},{"type":45,"tag":1587,"props":5590,"children":5591},{"style":1708},[5592],{"type":50,"value":1825},{"type":45,"tag":1587,"props":5594,"children":5595},{"style":1714},[5596],{"type":50,"value":132},{"type":45,"tag":1587,"props":5598,"children":5599},{"style":1708},[5600],{"type":50,"value":2176},{"type":45,"tag":1587,"props":5602,"children":5603},{"style":1714},[5604],{"type":50,"value":132},{"type":45,"tag":1587,"props":5606,"children":5607},{"style":1719},[5608],{"type":50,"value":5609},"delete",{"type":45,"tag":1587,"props":5611,"children":5612},{"style":1846},[5613],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5615,"children":5616},{"style":1714},[5617],{"type":50,"value":1853},{"type":45,"tag":1587,"props":5619,"children":5620},{"style":1846},[5621],{"type":50,"value":1858},{"type":45,"tag":1587,"props":5623,"children":5624},{"style":1714},[5625],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5627,"children":5628},{"style":1714},[5629],{"type":50,"value":1868},{"type":45,"tag":1587,"props":5631,"children":5632},{"style":1846},[5633],{"type":50,"value":1873},{"type":45,"tag":1587,"props":5635,"children":5636},{"style":1714},[5637],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5639,"children":5640},{"style":1708},[5641],{"type":50,"value":2159},{"type":45,"tag":1587,"props":5643,"children":5644},{"style":1714},[5645],{"type":50,"value":1905},{"type":45,"tag":1587,"props":5647,"children":5648},{"style":1714},[5649],{"type":50,"value":1905},{"type":45,"tag":1587,"props":5651,"children":5652},{"style":1846},[5653],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5655,"children":5656},{"style":1714},[5657],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5659,"children":5661},{"class":1589,"line":5660},12,[5662],{"type":45,"tag":1587,"props":5663,"children":5664},{"style":3105},[5665],{"type":50,"value":5666},"  \u002F\u002F No auth check. The server action is invokable by anyone who can POST to it.\n",{"type":45,"tag":1587,"props":5668,"children":5670},{"class":1589,"line":5669},13,[5671],{"type":45,"tag":1587,"props":5672,"children":5673},{"style":1714},[5674],{"type":50,"value":2551},{"type":45,"tag":46,"props":5676,"children":5677},{},[5678],{"type":45,"tag":66,"props":5679,"children":5680},{},[5681],{"type":50,"value":1975},{"type":45,"tag":1576,"props":5683,"children":5685},{"className":1696,"code":5684,"language":1698,"meta":1581,"style":1581},"'use server';\nexport async function deleteUser(userId: string) {\n  const session = await auth();\n  if (!session?.user?.isAdmin) throw new Error('unauthorized');\n  await db.user.delete({ where: { id: userId } });\n}\n",[5686],{"type":45,"tag":101,"props":5687,"children":5688},{"__ignoreMap":1581},[5689,5708,5751,5782,5861,5936],{"type":45,"tag":1587,"props":5690,"children":5691},{"class":1589,"line":1590},[5692,5696,5700,5704],{"type":45,"tag":1587,"props":5693,"children":5694},{"style":1714},[5695],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5697,"children":5698},{"style":1735},[5699],{"type":50,"value":5528},{"type":45,"tag":1587,"props":5701,"children":5702},{"style":1714},[5703],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5705,"children":5706},{"style":1714},[5707],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5709,"children":5710},{"class":1589,"line":1599},[5711,5715,5719,5723,5727,5731,5735,5739,5743,5747],{"type":45,"tag":1587,"props":5712,"children":5713},{"style":1817},[5714],{"type":50,"value":5337},{"type":45,"tag":1587,"props":5716,"children":5717},{"style":1759},[5718],{"type":50,"value":1762},{"type":45,"tag":1587,"props":5720,"children":5721},{"style":1759},[5722],{"type":50,"value":5351},{"type":45,"tag":1587,"props":5724,"children":5725},{"style":1719},[5726],{"type":50,"value":4518},{"type":45,"tag":1587,"props":5728,"children":5729},{"style":1714},[5730],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5732,"children":5733},{"style":1769},[5734],{"type":50,"value":5564},{"type":45,"tag":1587,"props":5736,"children":5737},{"style":1714},[5738],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5740,"children":5741},{"style":2873},[5742],{"type":50,"value":5573},{"type":45,"tag":1587,"props":5744,"children":5745},{"style":1714},[5746],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5748,"children":5749},{"style":1714},[5750],{"type":50,"value":1796},{"type":45,"tag":1587,"props":5752,"children":5753},{"class":1589,"line":31},[5754,5758,5762,5766,5770,5774,5778],{"type":45,"tag":1587,"props":5755,"children":5756},{"style":1759},[5757],{"type":50,"value":1804},{"type":45,"tag":1587,"props":5759,"children":5760},{"style":1708},[5761],{"type":50,"value":5376},{"type":45,"tag":1587,"props":5763,"children":5764},{"style":1714},[5765],{"type":50,"value":1814},{"type":45,"tag":1587,"props":5767,"children":5768},{"style":1817},[5769],{"type":50,"value":1820},{"type":45,"tag":1587,"props":5771,"children":5772},{"style":1719},[5773],{"type":50,"value":5389},{"type":45,"tag":1587,"props":5775,"children":5776},{"style":1846},[5777],{"type":50,"value":2539},{"type":45,"tag":1587,"props":5779,"children":5780},{"style":1714},[5781],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5783,"children":5784},{"class":1589,"line":1617},[5785,5789,5793,5797,5801,5805,5809,5813,5817,5821,5826,5831,5836,5840,5844,5849,5853,5857],{"type":45,"tag":1587,"props":5786,"children":5787},{"style":1817},[5788],{"type":50,"value":2213},{"type":45,"tag":1587,"props":5790,"children":5791},{"style":1846},[5792],{"type":50,"value":1381},{"type":45,"tag":1587,"props":5794,"children":5795},{"style":1714},[5796],{"type":50,"value":2222},{"type":45,"tag":1587,"props":5798,"children":5799},{"style":1708},[5800],{"type":50,"value":5417},{"type":45,"tag":1587,"props":5802,"children":5803},{"style":1714},[5804],{"type":50,"value":4627},{"type":45,"tag":1587,"props":5806,"children":5807},{"style":1708},[5808],{"type":50,"value":2176},{"type":45,"tag":1587,"props":5810,"children":5811},{"style":1714},[5812],{"type":50,"value":4627},{"type":45,"tag":1587,"props":5814,"children":5815},{"style":1708},[5816],{"type":50,"value":5434},{"type":45,"tag":1587,"props":5818,"children":5819},{"style":1846},[5820],{"type":50,"value":2231},{"type":45,"tag":1587,"props":5822,"children":5823},{"style":1817},[5824],{"type":50,"value":5825},"throw",{"type":45,"tag":1587,"props":5827,"children":5828},{"style":1714},[5829],{"type":50,"value":5830}," new",{"type":45,"tag":1587,"props":5832,"children":5833},{"style":1719},[5834],{"type":50,"value":5835}," Error",{"type":45,"tag":1587,"props":5837,"children":5838},{"style":1846},[5839],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5841,"children":5842},{"style":1714},[5843],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5845,"children":5846},{"style":1735},[5847],{"type":50,"value":5848},"unauthorized",{"type":45,"tag":1587,"props":5850,"children":5851},{"style":1714},[5852],{"type":50,"value":1732},{"type":45,"tag":1587,"props":5854,"children":5855},{"style":1846},[5856],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5858,"children":5859},{"style":1714},[5860],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5862,"children":5863},{"class":1589,"line":1626},[5864,5868,5872,5876,5880,5884,5888,5892,5896,5900,5904,5908,5912,5916,5920,5924,5928,5932],{"type":45,"tag":1587,"props":5865,"children":5866},{"style":1817},[5867],{"type":50,"value":4881},{"type":45,"tag":1587,"props":5869,"children":5870},{"style":1708},[5871],{"type":50,"value":1825},{"type":45,"tag":1587,"props":5873,"children":5874},{"style":1714},[5875],{"type":50,"value":132},{"type":45,"tag":1587,"props":5877,"children":5878},{"style":1708},[5879],{"type":50,"value":2176},{"type":45,"tag":1587,"props":5881,"children":5882},{"style":1714},[5883],{"type":50,"value":132},{"type":45,"tag":1587,"props":5885,"children":5886},{"style":1719},[5887],{"type":50,"value":5609},{"type":45,"tag":1587,"props":5889,"children":5890},{"style":1846},[5891],{"type":50,"value":1727},{"type":45,"tag":1587,"props":5893,"children":5894},{"style":1714},[5895],{"type":50,"value":1853},{"type":45,"tag":1587,"props":5897,"children":5898},{"style":1846},[5899],{"type":50,"value":1858},{"type":45,"tag":1587,"props":5901,"children":5902},{"style":1714},[5903],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5905,"children":5906},{"style":1714},[5907],{"type":50,"value":1868},{"type":45,"tag":1587,"props":5909,"children":5910},{"style":1846},[5911],{"type":50,"value":1873},{"type":45,"tag":1587,"props":5913,"children":5914},{"style":1714},[5915],{"type":50,"value":1863},{"type":45,"tag":1587,"props":5917,"children":5918},{"style":1708},[5919],{"type":50,"value":2159},{"type":45,"tag":1587,"props":5921,"children":5922},{"style":1714},[5923],{"type":50,"value":1905},{"type":45,"tag":1587,"props":5925,"children":5926},{"style":1714},[5927],{"type":50,"value":1905},{"type":45,"tag":1587,"props":5929,"children":5930},{"style":1846},[5931],{"type":50,"value":1786},{"type":45,"tag":1587,"props":5933,"children":5934},{"style":1714},[5935],{"type":50,"value":1918},{"type":45,"tag":1587,"props":5937,"children":5938},{"class":1589,"line":1635},[5939],{"type":45,"tag":1587,"props":5940,"children":5941},{"style":1714},[5942],{"type":50,"value":2551},{"type":45,"tag":89,"props":5944,"children":5946},{"id":5945},"investigation-playbook",[5947],{"type":50,"value":5948},"Investigation Playbook",{"type":45,"tag":46,"props":5950,"children":5951},{},[5952],{"type":50,"value":5953},"When you see a candidate:",{"type":45,"tag":58,"props":5955,"children":5956},{},[5957,6001,6019,6029,6039,6056,6066],{"type":45,"tag":62,"props":5958,"children":5959},{},[5960,5965,5967,5973,5975,5980,5981,5987,5988,5994,5995,6000],{"type":45,"tag":66,"props":5961,"children":5962},{},[5963],{"type":50,"value":5964},"Read the full handler and its wrappers.",{"type":50,"value":5966}," Decorators, class-level ",{"type":45,"tag":101,"props":5968,"children":5970},{"className":5969},[],[5971],{"type":50,"value":5972},"permission_classes",{"type":50,"value":5974},", router-level middleware, ",{"type":45,"tag":101,"props":5976,"children":5978},{"className":5977},[],[5979],{"type":50,"value":184},{"type":50,"value":324},{"type":45,"tag":101,"props":5982,"children":5984},{"className":5983},[],[5985],{"type":50,"value":5986},"beforeHandle",{"type":50,"value":324},{"type":45,"tag":101,"props":5989,"children":5991},{"className":5990},[],[5992],{"type":50,"value":5993},"preHandler",{"type":50,"value":324},{"type":45,"tag":101,"props":5996,"children":5998},{"className":5997},[],[5999],{"type":50,"value":490},{"type":50,"value":132},{"type":45,"tag":62,"props":6002,"children":6003},{},[6004,6009,6011,6017],{"type":45,"tag":66,"props":6005,"children":6006},{},[6007],{"type":50,"value":6008},"Find the route registration.",{"type":50,"value":6010}," ",{"type":45,"tag":101,"props":6012,"children":6014},{"className":6013},[],[6015],{"type":50,"value":6016},"rg -n \u003Cpath_or_name>",{"type":50,"value":6018},". Confirm which middleware is actually bound at runtime, not at declaration.",{"type":45,"tag":62,"props":6020,"children":6021},{},[6022,6027],{"type":45,"tag":66,"props":6023,"children":6024},{},[6025],{"type":50,"value":6026},"Read the query or ORM call.",{"type":50,"value":6028}," Does it scope by principal, ownership, or tenant?",{"type":45,"tag":62,"props":6030,"children":6031},{},[6032,6037],{"type":45,"tag":66,"props":6033,"children":6034},{},[6035],{"type":50,"value":6036},"Read the permission function if one is called.",{"type":50,"value":6038}," Does it fail closed on unknown inputs?",{"type":45,"tag":62,"props":6040,"children":6041},{},[6042,6047,6048,6054],{"type":45,"tag":66,"props":6043,"children":6044},{},[6045],{"type":50,"value":6046},"Check recent history.",{"type":50,"value":6010},{"type":45,"tag":101,"props":6049,"children":6051},{"className":6050},[],[6052],{"type":50,"value":6053},"git log -p -- \u003Cfile>",{"type":50,"value":6055},". An access check recently removed or weakened is worth investigating carefully.",{"type":45,"tag":62,"props":6057,"children":6058},{},[6059,6064],{"type":45,"tag":66,"props":6060,"children":6061},{},[6062],{"type":50,"value":6063},"Compare to siblings.",{"type":50,"value":6065}," If nearby handlers enforce a check this one does not, the delta is usually the bug.",{"type":45,"tag":62,"props":6067,"children":6068},{},[6069,6074,6076,6081,6083,6088,6090,6095,6097,6102],{"type":45,"tag":66,"props":6070,"children":6071},{},[6072],{"type":50,"value":6073},"Detect the framework and load the reference.",{"type":50,"value":6075}," The same-looking bare handler has different protection in Django (",{"type":45,"tag":101,"props":6077,"children":6079},{"className":6078},[],[6080],{"type":50,"value":1316},{"type":50,"value":6082},"), NestJS (",{"type":45,"tag":101,"props":6084,"children":6086},{"className":6085},[],[6087],{"type":50,"value":538},{"type":50,"value":6089},"), and Express (explicit ",{"type":45,"tag":101,"props":6091,"children":6093},{"className":6092},[],[6094],{"type":50,"value":168},{"type":50,"value":6096},"). Load the matching ",{"type":45,"tag":101,"props":6098,"children":6100},{"className":6099},[],[6101],{"type":50,"value":262},{"type":50,"value":6103}," for specifics.",{"type":45,"tag":46,"props":6105,"children":6106},{},[6107],{"type":50,"value":6108},"If the thread cannot be resolved with the files available, drop the finding or report with lower confidence.",{"type":45,"tag":89,"props":6110,"children":6112},{"id":6111},"output",[6113],{"type":50,"value":6114},"Output",{"type":45,"tag":46,"props":6116,"children":6117},{},[6118],{"type":50,"value":6119},"For each finding:",{"type":45,"tag":142,"props":6121,"children":6122},{},[6123,6133,6142,6152,6162,6204],{"type":45,"tag":62,"props":6124,"children":6125},{},[6126,6131],{"type":45,"tag":66,"props":6127,"children":6128},{},[6129],{"type":50,"value":6130},"File and line",{"type":50,"value":6132}," of the unsafe code.",{"type":45,"tag":62,"props":6134,"children":6135},{},[6136,6140],{"type":45,"tag":66,"props":6137,"children":6138},{},[6139],{"type":50,"value":673},{"type":50,"value":6141}," from the table above.",{"type":45,"tag":62,"props":6143,"children":6144},{},[6145,6150],{"type":45,"tag":66,"props":6146,"children":6147},{},[6148],{"type":50,"value":6149},"What is wrong",{"type":50,"value":6151},", in one sentence.",{"type":45,"tag":62,"props":6153,"children":6154},{},[6155,6160],{"type":45,"tag":66,"props":6156,"children":6157},{},[6158],{"type":50,"value":6159},"Who is affected and how",{"type":50,"value":6161},": which caller, which resource, what action.",{"type":45,"tag":62,"props":6163,"children":6164},{},[6165,6170,6172,6178,6180,6186,6188,6194,6196,6202],{"type":45,"tag":66,"props":6166,"children":6167},{},[6168],{"type":50,"value":6169},"Trace",{"type":50,"value":6171},": the specific path you followed (e.g., \"route registered at ",{"type":45,"tag":101,"props":6173,"children":6175},{"className":6174},[],[6176],{"type":50,"value":6177},"routes\u002Fadmin.ts:12",{"type":50,"value":6179}," with only ",{"type":45,"tag":101,"props":6181,"children":6183},{"className":6182},[],[6184],{"type":50,"value":6185},"requireAuth",{"type":50,"value":6187},", no admin check; handler at ",{"type":45,"tag":101,"props":6189,"children":6191},{"className":6190},[],[6192],{"type":50,"value":6193},"admin\u002Fusers.ts:40",{"type":50,"value":6195}," calls ",{"type":45,"tag":101,"props":6197,"children":6199},{"className":6198},[],[6200],{"type":50,"value":6201},"db.user.delete",{"type":50,"value":6203}," with id from body\").",{"type":45,"tag":62,"props":6205,"children":6206},{},[6207,6212],{"type":45,"tag":66,"props":6208,"children":6209},{},[6210],{"type":50,"value":6211},"Fix",{"type":50,"value":6213},": the concrete change that closes the hole. Name the filter field, the missing guard, the permission class to apply. \"Add an ownership filter\" is not enough.",{"type":45,"tag":46,"props":6215,"children":6216},{},[6217,6219,6224],{"type":50,"value":6218},"Group findings by severity. Lead with ",{"type":45,"tag":101,"props":6220,"children":6222},{"className":6221},[],[6223],{"type":50,"value":706},{"type":50,"value":132},{"type":45,"tag":6226,"props":6227,"children":6228},"style",{},[6229],{"type":50,"value":6230},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":6232,"total":2301},[6233,6248,6256,6272,6283,6294,6310],{"slug":6234,"name":6234,"fn":6235,"description":6236,"org":6237,"tags":6238,"stars":27,"repoUrl":28,"updatedAt":6247},"vercel-deepsec","scan web applications for security vulnerabilities","Detects broad web application security vulnerabilities using the Vercel DeepSec benchmark prompt. Use when benchmarking security review coverage or running an open-ended appsec scan for auth bypass, missing auth, XSS, RCE, SQL injection, SSRF, path traversal, secrets, weak crypto, unsafe redirects, webhook verification, Next.js Server Actions, Lua\u002FOpenResty, Go, cache poisoning, or header trust bugs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6239,6242,6243,6244],{"name":6240,"slug":6241,"type":16},"Audit","audit",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":6245,"slug":6246,"type":16},"Vercel","vercel","2026-05-05T05:29:23.090902",{"slug":4,"name":4,"fn":5,"description":6,"org":6249,"tags":6250,"stars":27,"repoUrl":28,"updatedAt":29},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6251,6252,6253,6254,6255],{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":25,"slug":26,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"slug":6257,"name":6257,"fn":6258,"description":6259,"org":6260,"tags":6261,"stars":27,"repoUrl":28,"updatedAt":6271},"wrdn-code-execution","detect code and command execution bugs","Detects bugs where untrusted input reaches a sink that produces code or command execution on the server. Covers command\u002Fshell injection, unsafe deserialization, server-side template injection, eval\u002FFunction\u002Fvm reached by user data, XXE-to-RCE gadgets, and prototype pollution that lands on a code-executing sink. Run on any diff touching subprocess\u002Fexec calls, template rendering, deserialization of bytes, XML parsing, or deep-merge of user-controlled objects.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6262,6265,6266,6269,6270],{"name":6263,"slug":6264,"type":16},"Backend","backend",{"name":25,"slug":26,"type":16},{"name":6267,"slug":6268,"type":16},"Debugging","debugging",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},"2026-04-29T05:41:39.861655",{"slug":6273,"name":6273,"fn":6274,"description":6275,"org":6276,"tags":6277,"stars":27,"repoUrl":28,"updatedAt":6282},"wrdn-data-exfil","detect data exfiltration and SSRF bugs","Detects bugs where untrusted input reaches a sink that leaks data beyond its intended scope. Covers SSRF (including cloud metadata, internal services, image proxies), path traversal and archive zip-slip, SQL\u002FNoSQL injection enabling bulk reads, XXE file read, response serializers over-exposing internal fields, verbose error pages, logs capturing secrets, and CSV\u002Fformula injection in exports. Run on any diff touching HTTP clients with user URLs, file I\u002FO with user paths, raw queries, XML parsing, response serializers, error handlers, or export pipelines.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6278,6279,6280,6281],{"name":6263,"slug":6264,"type":16},{"name":25,"slug":26,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},"2026-04-29T05:41:42.567486",{"slug":6284,"name":6284,"fn":6285,"description":6286,"org":6287,"tags":6288,"stars":27,"repoUrl":28,"updatedAt":6293},"wrdn-dos-review","identify denial-of-service vulnerabilities in code","Finds availability \u002F denial-of-service bugs reachable from untrusted input — unbounded allocation, uncontrolled recursion, non-terminating loops, decompression bombs, panic\u002Fresource-leak, super-linear output amplification, algorithmic-complexity \u002F ReDoS catastrophic regex backtracking, and bounds that are present but ineffective (wrong dimension, applied too late, under-counting cost, or defaulted off). Use for DoS and resource-exhaustion audits, CPU-complexity and cost-limit \u002F quota-accuracy review, parser\u002Fdecoder\u002Fdeserialization hardening, and crash-safety review of code that processes attacker-controlled bytes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6289,6290,6291,6292],{"name":25,"slug":26,"type":16},{"name":6267,"slug":6268,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},"2026-07-18T05:47:48.104703",{"slug":6295,"name":6295,"fn":6296,"description":6297,"org":6298,"tags":6299,"stars":27,"repoUrl":28,"updatedAt":6309},"wrdn-gha-workflows","detect GitHub Actions workflow vulnerabilities","Detects exploitable GitHub Actions workflow vulnerabilities, including pull_request_target pwn requests, unsafe PR checkout, expression injection in run steps and actions\u002Fgithub-script blocks, workflow_dispatch and workflow_call input command injection, comment- and discussion-triggered commands, TOCTOU between approval and checkout, secret exposure, broad permissions, reusable workflows that consume undeclared secrets, ArtiPACKED-style token leaks through uploaded artifacts, cache poisoning and eviction-stuffing, supply-chain risk from unpinned third-party actions (tj-actions\u002Fchanged-files class), and self-hosted runner abuse. Run on diffs touching .github\u002Fworkflows, action.yml, action.yaml, repo-local actions, or CI-loaded scripts and config.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6300,6303,6304,6307,6308],{"name":6301,"slug":6302,"type":16},"CI\u002FCD","ci-cd",{"name":25,"slug":26,"type":16},{"name":6305,"slug":6306,"type":16},"GitHub Actions","github-actions",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},"2026-04-29T05:41:43.93205",{"slug":6311,"name":6311,"fn":6312,"description":6313,"org":6314,"tags":6315,"stars":27,"repoUrl":28,"updatedAt":6325},"wrdn-pii","detect PII and confidential data in code","Detects real personally identifiable information, customer identifiers, and customer-confidential business data in code changes. Use when asked to find PII, customer IPs, real email addresses, revenue data, billing data, personal data, privacy leaks, customer info in logs, PII in URLs, or accidental production data in tests, fixtures, comments, docs, config, telemetry, or API responses.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6316,6317,6320,6323,6324],{"name":25,"slug":26,"type":16},{"name":6318,"slug":6319,"type":16},"Compliance","compliance",{"name":6321,"slug":6322,"type":16},"Privacy","privacy",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},"2026-04-29T05:41:38.512082",{"items":6327,"total":6496},[6328,6351,6365,6380,6394,6411,6425,6439,6447,6458,6468,6483],{"slug":6329,"name":6329,"fn":6330,"description":6331,"org":6332,"tags":6333,"stars":6348,"repoUrl":6349,"updatedAt":6350},"xcodebuildmcp","build and test Apple apps with XcodeBuildMCP","Official skill for XcodeBuildMCP. Use when doing iOS\u002FmacOS\u002FwatchOS\u002FtvOS\u002FvisionOS work (build, test, run, debug, log, UI automation).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6334,6335,6338,6341,6342,6345],{"name":6267,"slug":6268,"type":16},{"name":6336,"slug":6337,"type":16},"iOS","ios",{"name":6339,"slug":6340,"type":16},"macOS","macos",{"name":9,"slug":8,"type":16},{"name":6343,"slug":6344,"type":16},"Testing","testing",{"name":6346,"slug":6347,"type":16},"Xcode","xcode",6176,"https:\u002F\u002Fgithub.com\u002Fgetsentry\u002FXcodeBuildMCP","2026-04-06T18:13:34.8719",{"slug":6352,"name":6352,"fn":6353,"description":6354,"org":6355,"tags":6356,"stars":6348,"repoUrl":6349,"updatedAt":6364},"xcodebuildmcp-cli","build and test Apple apps via CLI","Official skill for the XcodeBuildMCP CLI. Use when doing iOS\u002FmacOS\u002FwatchOS\u002FtvOS\u002FvisionOS work (build, test, run, debug, log, UI automation).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6357,6360,6361,6362,6363],{"name":6358,"slug":6359,"type":16},"CLI","cli",{"name":6336,"slug":6337,"type":16},{"name":6339,"slug":6340,"type":16},{"name":6343,"slug":6344,"type":16},{"name":6346,"slug":6347,"type":16},"2026-04-06T18:13:36.13414",{"slug":6366,"name":6366,"fn":6367,"description":6368,"org":6369,"tags":6370,"stars":6377,"repoUrl":6378,"updatedAt":6379},"agents-md","maintain project instruction files","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.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6371,6374],{"name":6372,"slug":6373,"type":16},"Documentation","documentation",{"name":6375,"slug":6376,"type":16},"Engineering","engineering",861,"https:\u002F\u002Fgithub.com\u002Fgetsentry\u002Fskills","2026-05-15T06:16:29.695991",{"slug":6381,"name":6381,"fn":6382,"description":6383,"org":6384,"tags":6385,"stars":6377,"repoUrl":6378,"updatedAt":6393},"blog-writing-guide","write and review engineering blog posts","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 product announcement, create an engineering deep-dive, or produce any written content destined for the Sentry blog or developer audience. Also trigger when the user mentions \"blog post,\" \"blog draft,\" \"write-up,\" \"announcement post,\" \"engineering post,\" \"deep dive,\" \"postmortem,\" or asks for help with technical writing for Sentry. Even if the user just says \"help me write about [feature\u002Ftopic]\" — if it sounds like it could become a Sentry blog post, use this skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6386,6389,6390],{"name":6387,"slug":6388,"type":16},"Communications","communications",{"name":9,"slug":8,"type":16},{"name":6391,"slug":6392,"type":16},"Technical Writing","technical-writing","2026-05-15T06:16:33.38217",{"slug":6395,"name":6395,"fn":6396,"description":6397,"org":6398,"tags":6399,"stars":6377,"repoUrl":6378,"updatedAt":6410},"brand-guidelines","write copy following Sentry 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.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6400,6403,6406,6407],{"name":6401,"slug":6402,"type":16},"Branding","branding",{"name":6404,"slug":6405,"type":16},"Content Creation","content-creation",{"name":9,"slug":8,"type":16},{"name":6408,"slug":6409,"type":16},"UX Copy","ux-copy","2026-05-15T06:16:22.395707",{"slug":6412,"name":6412,"fn":6413,"description":6414,"org":6415,"tags":6416,"stars":6377,"repoUrl":6378,"updatedAt":6424},"claude-settings-audit","generate Claude Code settings permissions","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.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6417,6420,6423],{"name":6418,"slug":6419,"type":16},"Claude Code","claude-code",{"name":6421,"slug":6422,"type":16},"Configuration","configuration",{"name":14,"slug":15,"type":16},"2026-05-15T06:16:44.335977",{"slug":6426,"name":6426,"fn":6427,"description":6428,"org":6429,"tags":6430,"stars":6377,"repoUrl":6378,"updatedAt":6438},"code-review","perform code reviews for Sentry projects","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.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6431,6433,6434,6437],{"name":6432,"slug":6426,"type":16},"Code Review",{"name":6375,"slug":6376,"type":16},{"name":6435,"slug":6436,"type":16},"Performance","performance",{"name":14,"slug":15,"type":16},"2026-05-15T06:16:35.824864",{"slug":6440,"name":6440,"fn":6441,"description":6442,"org":6443,"tags":6444,"stars":6377,"repoUrl":6378,"updatedAt":6446},"code-simplifier","simplify and refine source code","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 project-specific best practices.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6445],{"name":25,"slug":26,"type":16},"2026-05-15T06:16:32.127981",{"slug":6448,"name":6448,"fn":6449,"description":6450,"org":6451,"tags":6452,"stars":6377,"repoUrl":6378,"updatedAt":6457},"commit","create commits with Sentry conventions","Use for every request to commit changes or draft a commit message. Creates Sentry-style conventional commits with issue references.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6453,6456],{"name":6454,"slug":6455,"type":16},"Git","git",{"name":9,"slug":8,"type":16},"2026-07-18T05:15:10.723937",{"slug":6459,"name":6459,"fn":6460,"description":6461,"org":6462,"tags":6463,"stars":6377,"repoUrl":6378,"updatedAt":6467},"create-branch","create git branches for Sentry workflows","Create a git branch following Sentry naming conventions. Use when asked to \"create a branch\", \"new branch\", \"start a branch\", \"make a branch\", \"switch to a new branch\", or when starting new work on the default branch.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6464,6465,6466],{"name":6375,"slug":6376,"type":16},{"name":6454,"slug":6455,"type":16},{"name":9,"slug":8,"type":16},"2026-05-15T06:16:39.458431",{"slug":6469,"name":6469,"fn":6470,"description":6471,"org":6472,"tags":6473,"stars":6377,"repoUrl":6378,"updatedAt":6482},"django-access-review","review Django access control and IDOR","Django access control and IDOR security review. Use when reviewing Django views, DRF viewsets, ORM queries, or any Python\u002FDjango code handling user authorization. Trigger keywords: \"IDOR\", \"access control\", \"authorization\", \"Django permissions\", \"object permissions\", \"tenant isolation\", \"broken access\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6474,6475,6476,6479,6481],{"name":21,"slug":22,"type":16},{"name":25,"slug":26,"type":16},{"name":6477,"slug":6478,"type":16},"Django","django",{"name":6480,"slug":1580,"type":16},"Python",{"name":14,"slug":15,"type":16},"2026-05-15T06:16:43.098698",{"slug":6484,"name":6484,"fn":6485,"description":6486,"org":6487,"tags":6488,"stars":6377,"repoUrl":6378,"updatedAt":6495},"django-perf-review","review and optimize Django performance","Django performance code review. Use when asked to \"review Django performance\", \"find N+1 queries\", \"optimize Django\", \"check queryset performance\", \"database performance\", \"Django ORM issues\", or audit Django code for performance problems.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6489,6490,6493,6494],{"name":6432,"slug":6426,"type":16},{"name":6491,"slug":6492,"type":16},"Database","database",{"name":6477,"slug":6478,"type":16},{"name":6435,"slug":6436,"type":16},"2026-05-15T06:16:24.832813",88]