agentsclimarketplace

Access control

Skill hereshecodes/secureskills/skills/access-control

Security skills for AI coding agents. Install once, write secure code every time.

Install
npx -y skills add hereshecodes/secureskills --skill access-control

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when writing authorization logic, route guards, or resource access

SKILL.md

3.2 KB, as published. Nobody here has run it

Access Control

Every protected resource must verify that the requesting user has permission. Default to deny.

Related: authentication, api-security, security-context

Rule 1: Verify Resource Ownership

Never trust route parameters alone. Verify the user owns or can access the resource.

// WRONG — anyone can access any user's data
app.get('/users/:id/settings', async (req, res) => {
  const settings = await getSettings(req.params.id);
  res.json(settings);
});

// RIGHT — verify ownership
app.get('/users/:id/settings', async (req, res) => {
  if (req.params.id !== req.user.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const settings = await getSettings(req.params.id);
  res.json(settings);
});

Rule 2: Default to Deny

Protect everything by default. Explicitly mark public routes.

# WRONG — protect individual routes (easy to forget one)
@app.route('/admin')
@login_required
def admin(): ...

# RIGHT — protect everything, whitelist public routes
@app.before_request
def require_auth():
    public = ['/login', '/signup', '/health']
    if request.path not in public and not current_user.is_authenticated:
        return redirect('/login')

Rule 3: Check Permissions in Multiple Layers

Don't rely on route middleware alone. Check in the service layer too.

// WRONG — only checked at route level
router.delete('/posts/:id', requireAdmin, deletePost);

// RIGHT — checked at route AND service level
router.delete('/posts/:id', requireAdmin, deletePost);

async function deletePost(postId, requestingUser) {
  const post = await getPost(postId);
  if (!post) throw new NotFoundError();
  if (!requestingUser.isAdmin && post.authorId !== requestingUser.id) {
    throw new ForbiddenError();
  }
  await removePost(postId);
}

Rule 4: Use Role-Based or Policy-Based Access

Don't scatter permission checks as ad-hoc if statements. Centralize them.

// WRONG — ad-hoc checks everywhere
if (user.role === 'admin' || user.role === 'editor') { ... }

// RIGHT — centralized policy
const policies = {
  'posts:delete': (user, post) => user.isAdmin || post.authorId === user.id,
  'users:manage': (user) => user.isAdmin,
};

function authorize(action, user, resource) {
  return policies[action]?.(user, resource) ?? false;
}

Rule 5: Never Expose Internal IDs Unnecessarily

Use UUIDs for public-facing identifiers. Sequential IDs reveal data volume and are easily enumerated.

// WRONG — sequential IDs in URLs
GET /api/invoices/1042

// RIGHT — UUIDs in URLs
GET /api/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890

Quick Reference

DoDon't
Verify ownership on every requestTrust route parameters
Default to deny, whitelist public routesProtect routes individually (easy to miss)
Check permissions in routes AND servicesRely on a single middleware layer
Centralize permission logicScatter if-statements across codebase
Use UUIDs for public-facing IDsExpose sequential database IDs

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.