Skip to content
Back to skills

Feathers Review

ASecurity

Review FeathersJS v5 code for correctness, security, and idiomatic structure before it ships. Use whenever the user asks to review, audit, or sanity-check a Feathers service, hook, schema, or PR, or asks "is this secure / is this right", or right after generating or editing Feathers code. Focuses on the things that bite Feathers apps — missing authentication, authorization that isn't enforced in query resolvers, sensitive fields leaking through missing external resolvers, unregistered service...

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added June 2, 2026
developmentrustgosqlapisecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 2, 2026

npx -y skills add hassan4702/feathers-plugin --skill feathers-review --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Feathers Review?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Feathers Review
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hassan4702-feathers-review/badge)](https://www.skillsdirectory.com/skills/hassan4702-feathers-review)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: feathers-review
description: Review FeathersJS v5 code for correctness, security, and idiomatic structure before it ships. Use whenever the user asks to review, audit, or sanity-check a Feathers service, hook, schema, or PR, or asks "is this secure / is this right", or right after generating or editing Feathers code. Focuses on the things that bite Feathers apps — missing authentication, authorization that isn't enforced in query resolvers, sensitive fields leaking through missing external resolvers, unregistered services/hooks, and schema/migration drift. Trigger proactively after writing Feathers code even if review wasn't explicitly requested.
---

# FeathersJS Code Review

Walk the changed/affected files and check the items below. Report findings grouped by severity (Critical → Warning → Style), each with the file, the problem, and a concrete fix. Don't just restate the code — say what's wrong and what to change.

## Critical (security / correctness)

1. **Authentication present.** Each non-public service should have `authenticate('jwt')` in `around.all`. Flag any service exposed externally (`methods` includes mutating verbs) without it. Confirm "public" services are public on purpose.
2. **Authorization actually enforced.** Ownership/tenancy checks belong in the **query resolver** (`<name>QueryResolver`) so they cover `find`/`get`/`patch`/`remove`, not only in a data resolver (which misses reads/removes). Verify writes are pinned to `context.params.user`, not to a client-supplied id.
3. **Sensitive fields hidden.** Every schema with secrets (`password`, tokens, internal ids) needs an **external resolver** setting them to `undefined`. A missing external resolver leaks them in API responses.
4. **Ownership derived from auth, not body.** `userId`/`ownerId` should be set in the data resolver from `context.params.user`, never trusted from `context.data`.
5. **Service is registered.** The configure function must be `app.configure(...)`-ed in `src/services/index.ts`. An unregistered service silently 404s.
6. **Hooks are wired.** A hook/resolver that's defined but not added to the `.hooks({...})` object never runs — check each validator/resolver is referenced.
7. **`additionalProperties: false`** on data schemas, so unexpected fields are rejected rather than written.
8. **Query surface is minimal.** `querySyntax(...)` should list only properties safe to filter/sort on; sensitive or expensive columns shouldn't be queryable.

## Warning (robustness)

- **`await next()` in around hooks** — missing it skips the service call and all downstream hooks.
- **Internal vs external calls** — guards that read `context.params.user` should also consider `context.params.provider` (`undefined` = internal) so server-side calls aren't wrongly blocked or wrongly trusted.
- **Typed errors** — throw `@feathersjs/errors` (`BadRequest`, `NotAuthenticated`, `Forbidden`, `NotFound`) rather than generic `Error`, so HTTP status codes are correct.
- **Schema ↔ migration drift** (SQL) — every new/changed/removed field needs a matching Knex migration with a working `down`. Flag schema edits with no migration.
- **Unique `$id`** — duplicated schema `$id` values collide in the validator registry.
- **Pagination** — large collections should set/respect `paginate`; unbounded `find` is a DoS/perf risk.
- **By-reference mutation** of `context.data` / `context.params.query` — spread into new objects.

## Style / idiom

- Four-file layout per service (`.ts`, `.class.ts`, `.schema.ts`, `.shared.ts`); logic in the expected file.
- Types derived via `Static<typeof schema>`, not hand-written parallel interfaces.
- Reuse `all` hooks instead of repeating the same hook across every method.
- Match the project's existing conventions (id type, ESM/CJS, db adapter, linter) — read a sibling service to confirm before suggesting changes.

## Output format

```
## Review: <files>

### Critical
- [services/messages/messages.ts] No authenticate('jwt') in around.all — the messages
  service is writable over REST by anyone. Add it as the first around.all hook.

### Warning
- [services/messages/messages.schema.ts] userId added to schema but no migration found.
  Add a Knex migration adding the column with a foreign key to users.id.

### Style
- ...

### Looks good
- External resolver correctly hides password.
```

If everything checks out, say so plainly rather than inventing issues.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.