Django Access Review
getsentry/skills
Django access control and IDOR security review. An agent skill from getsentry/skills.
Explains authorization in an Arandu Go application: write a Policy, get a security.Grant through security.Authorize, re-authorize each row, and keep tenant isolation.
$ npx skills add arandu-io/arandu --skill arandu-policy -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install arandu-io/arandu arandu-policy --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/arandu-policy .claude/skills/arandu-policy && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .claude/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policyType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add arandu-io/arandu --skill arandu-policy -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install arandu-io/arandu arandu-policy --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/arandu-policy .agents/skills/arandu-policy && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .agents/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add arandu-io/arandu --skill arandu-policy -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install arandu-io/arandu arandu-policy --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/arandu-policy .cursor/skills/arandu-policy && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .cursor/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/arandu-io/arandu.git --path .agents/skills/arandu-policy--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add arandu-io/arandu --skill arandu-policy -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install arandu-io/arandu arandu-policy --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/arandu-policy .gemini/skills/arandu-policy && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .gemini/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install arandu-io/arandu arandu-policyInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add arandu-io/arandu --skill arandu-policy -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/arandu-policy .github/skills/arandu-policy && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .github/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add arandu-io/arandu --skill arandu-policy -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install arandu-io/arandu arandu-policy --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/arandu-io/arandu.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/arandu-policy .opencode/skills/arandu-policy && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "arandu-policy" agent skill from https://github.com/arandu-io/arandu/tree/main/.agents/skills/arandu-policy into .opencode/skills/arandu-policy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "arandu-policy", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
arandu-policyExplains authorization in an Arandu Go application: write a Policy, get a security.Grant through security.Authorize, re-authorize each row, and keep tenant isolation.
In Arandu, security.Grant has only unexported fields, so code outside its package cannot build one, and every Model read or write requires one: the query terminals First, Get and Value, and an entity's Save and Delete. A service that never asks a Policy has nothing to pass, so unauthorized access fails to compile. The tenant is read from the grant with data.Tenant, never from the path, body or a header. The skill warns against deleting the grant parameter just to make code compile, since that parameter is what keeps the query safe.
The procedure is that a Policy implements Can, returning nil to allow and an error to deny, with actions as constants, tenant isolation checked first and no default branch that allows. A service calls security.Authorize with the policy, subject, action and resource, and only a nil result yields the Grant. After loading a record it authorizes the row as well, since otherwise any user in the tenant can see it and aru doctor reports resource-not-reauthorized, and writes check the stored row rather than what the request claims. Reads such as List, Find, projections, reports and exports need a Grant too, and SystemGrant is covered as well.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit b8a4273. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
gobashFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Arandu Policy and Grants loads about 1.9k tokens when it runs. Until then it costs about 154 tokens; SKILL.md has 813 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from arandu-io/arandu at commit b8a4273, republished under its MIT licence (© arandu-io). 813 words, ~1,904 tokens.
.claude/skills/arandu-policy/SKILL.md (or your agent's skills folder).Who may take an action on a record, the tenant a query reads, a Grant a call
asks for, and the one escape hatch for work with nobody asking. Which roles a
member holds inside an organization is arandu-ecosystem (arandu-permission);
this skill is the decision about a record.
app/Policies/NotePolicy.go, the example's rules, and the Get and
Publish methods of app/Services/NoteService.go, which ask it.auth.Grant has only unexported fields: nothing outside its package builds
one. Every read and write through a model takes one. A service that reaches
the database without asking a Policy has nothing to pass, and does not
compile. The safe path is not documented; the unsafe path is absent.All from github.com/arandu-io/hesape/auth:
| symbol | contract |
|---|---|
Action | a named constant, entity first: NoteView auth.Action = "note.view" |
Policy[T] | Can(ctx, s auth.Subject, a auth.Action, x T) error: nil allows, an error denies; it never builds a Grant |
Authorize | auth.Authorize(ctx, policy, subject, action, resource) (auth.Grant, error): runs Can, and only when it answers nil issues the Grant |
Grant | what every terminal of a generated query, Save and Delete take; g.Check(action) asks whether it was issued for an action |
Tenant | auth.Tenant(g), the only source of a tenant |
SystemGrant | auth.SystemGrant(action, tenant), for work with no subject: a seeder, a job, a command, main.go |
Subject | who is asking: ID, Tenant, Roles, HasRole |
NotePublish.Can, inside the custom block: tenant isolation first, the
zero subject refused, then one case per action, and nothing that allows by
default -- the function denies by falling through.NoteService.Publish authorizes
NotePublish against the stored note and its stored author.auth.SystemGrant in a seeder, a job, a
command or main.go. Anywhere else it carries its reason on the line
before: //arandu:system-grant <reason>, as the example's listener does.aru make:policy <module> writes a policy that denies every actionaru make:module writes one with the modulearu action:list lists the actions the source declares, with the constant and the line of eachA rule about the row, and the double authorization that reads it:
package example
import (
"context"
"fmt"
"github.com/arandu-io/hesape/auth"
"github.com/arandu-io/hesape/database"
models "<module>/app/Models"
)
// NotePin is pinning one note.
const NotePin auth.Action = "note.pin"
// PinPolicy decides who pins a note: its author, in its tenant.
type PinPolicy struct{}
var _ auth.Policy[models.Note] = PinPolicy{}
// Can answers nil to allow and an error to deny, and denies by falling through.
func (PinPolicy) Can(_ context.Context, s auth.Subject, a auth.Action, n models.Note) error {
if n.ID != "" && n.TenantID != s.Tenant {
return fmt.Errorf("note belongs to another tenant")
}
if s.ID == "" || s.Tenant == "" {
return fmt.Errorf("pinning needs somebody signed in")
}
if a == NotePin && (n.ID == "" || n.OwnedBy(s.ID)) {
return nil
}
return fmt.Errorf("no rule allows %s on note", a)
}
// Pin reads the row through a Grant, authorizes the row it read, and writes
// with the Grant that decision issued.
func Pin(ctx context.Context, db *database.DB, actor auth.Subject, id string) error {
g, err := auth.Authorize(ctx, PinPolicy{}, actor, NotePin, models.Note{})
if err != nil {
return err
}
note, err := models.Notes(db).FindOrFail(ctx, g, id)
if err != nil {
return err
}
g, err = auth.Authorize(ctx, PinPolicy{}, actor, NotePin, *note)
if err != nil {
return err
}
note.Pinned = true
_, err = note.Save(ctx, g)
return err
}tenant-from-request, tenant-from-header. It is auth.Tenant(g).resource-not-reauthorized.is_admin flag or an ACL table: roles are
arandu-permission's (arandu-ecosystem), and the policy reads them off the
subject.A rule goes in the custom block of Can; an action is a constant beside the
generated ones. A rule that depends on another record -- the note a comment
belongs to -- is decided by loading that record through its own service and
policy, as CommentService loads the note, never by reading its table here.
A policy is a value: the service holds it as a field and passes it to
auth.Authorize. Nothing registers it, and nothing in bootstrap/app.go
changes.
SystemGrant exists. What catches a handler using it is aru doctor
(system-grant-outside-scope), not the type system, and the marker excuses the
line it is on and nothing else. A table with no tenant column is invisible to
the tenant test, and its isolation rests on every query of it taking a Grant.
Run them all, in this order, as AGENTS.md lists them:
export GOWORK=off
aru model:build --check
aru view:build
gofmt -l $(find . -name '*.go' -not -path '*/testdata/*' -not -name '*.kyse.go')
go vet ./...
bash tests/test-layout-guard.sh
go test -race ./...
go build ./...
aru doctor<!-- arandu:begin custom -->
<!-- arandu:end custom -->
© arandu-io, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/arandu-policy of arandu-io/arandu.
Open the folder on GitHubat commit b8a4273
Arandu Policy and Grants next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Arandu Policy and Grants this skillarandu-io/arandu | 281 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Django Access Reviewgetsentry/skills | 1k | 3 repos | ~2.6k | Automated safety check: Notes | Apache-2.0 | |
| Cb Security HardeningBlkLeg/CircuitBreaker | 201 | — | ~2.1k | Automated safety check: Pass | MIT | |
| Openfdd Mt Securitybbartling/open-fdd | 173 | — | ~2.2k | Automated safety check: Pass | Custom licence | |
| Abp Authorizationabpframework/abp | 14k | — | ~1.3k | Automated safety check: Pass | LGPL-3.0 | |
| Security Review ChecklistZeroDeng01/sublinkPro | 1.7k | — | ~2.3k | Automated safety check: Pass | MIT |
getsentry/skills
Django access control and IDOR security review. An agent skill from getsentry/skills.
BlkLeg/CircuitBreaker
Enforces Circuit Breaker security hardening conventions across backend, frontend, Docker, and nginx.
bbartling/open-fdd
Multi-tenant authz, pre-auth disclosure hardening, and Kali disposition.
abpframework/abp
ABP permission system - PermissionDefinitionProvider, [Authorize] attribute, CheckPolicyAsync, IsGrantedAsync, ICurrentUser, IPermissionManager, multi-tenancy side.
ZeroDeng01/sublinkPro
Checklist-driven security review for changes to authentication, authorization, MFA, secrets, input validation and other security-critical code.
supercheck-io/supercheck
Work on Supercheck authentication, RBAC, tenant isolation, sessions, API and trigger keys, invitations, project membership, project variables, OAuth, super-admin behavior, SSRF, or…
arandu-io/arandu
Answering a program rather than a person in an Arandu (Go) application -- a JSON Resource, a JSON answer from the same routes the pages use, problem+json errors, bearer-token authentication and…
arandu-io/arandu
Work that does not happen inside the request in an Arandu (Go) application -- background jobs and the worker, scheduled tasks, domain events through the outbox, listeners, notifications, mail and…
arandu-io/arandu
Decides whether a feature belongs in the application or in one of five shared Arandu modules before adding permissions, wallets, tags, Markdown rendering or API docs.
arandu-io/arandu
Start here for any change to an Arandu (Go) application that adds or changes behaviour -- "add invoices", "let users publish a post", "send a weekly report", "call the payment provider", "expose…
arandu-io/arandu
Controllers, requests and routes of an Arandu (Go) application -- the seven resource actions, a resource nested under another, a singleton, a single-action (invokable) controller, a named action…
arandu-io/arandu
Reaching other systems from an Arandu (Go) application, and letting them reach it -- the client of an external API with its interface and fake, webhooks sent and received, and tools, resources and…
Works with
Categories
Explains authorization in an Arandu Go application: write a Policy, get a security.Grant through security.Authorize, re-authorize each row, and keep tenant isolation. Grant has only unexported fields, so code outside its package cannot build one, and every Model read or write requires one: the query terminals First, Get and Value, and an entity's Save and Delete. A service that never asks a Policy has nothing to pass, so unauthorized access fails to compile.
Arandu Policy and Grants fits situations like: writing or changing who may read or change a record in an Arandu app; fixing a compile error that asks for a security.Grant; adding tenant isolation to a new service or Model query; writing a Policy for a new resource.
Run `npx skills add arandu-io/arandu --skill arandu-policy -a claude-code`. Or copy the skill folder (.agents/skills/arandu-policy in arandu-io/arandu) into .claude/skills/arandu-policy in your project. Claude Code loads it when a task matches its description.
Run `npx skills add arandu-io/arandu --skill arandu-policy -a codex`. Or copy the skill folder (.agents/skills/arandu-policy in arandu-io/arandu) into .agents/skills/arandu-policy in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add arandu-io/arandu --skill arandu-policy -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/arandu-policy, .gemini/skills/arandu-policy, .github/skills/arandu-policy and .opencode/skills/arandu-policy in your project.
Going by SKILL.md and its folder, Arandu Policy and Grants needs the command-line tools its instructions call (go and bash). Our summary lists: An Arandu Go project.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Arandu Policy and Grants is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 1.9k tokens (SKILL.md is roughly 7.6k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Arandu Policy and Grants: Django Access Review (getsentry/skills, 1k stars), Cb Security Hardening (BlkLeg/CircuitBreaker, 201 stars), Openfdd Mt Security (bbartling/open-fdd, 173 stars) and Abp Authorization (abpframework/abp, 14k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
arandu-io (a GitHub organization) maintains it in arandu-io/arandu, which has 281 GitHub stars. The repository holds 12 skills in this directory. The repository was last updated on October 10, 2026.
Source: arandu-io/arandu on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.