Skip to content

Security: GearSite/JSON-API

Security

SECURITY.md

Security Policy

Report a vulnerability

Email security@gearsite.net. Put "gearsite/api" in the subject.

CAUTION: do not open a public issue for a vulnerability. A public report tells everyone who runs this library about the problem before a fix exists.

What to include

A report needs enough for someone else to reproduce the problem:

  • The smallest case that shows it. A failing test is best. A serializer plus a request is usually enough.
  • The request, when one is involved: the method, the URL with its query parameters, and the body.
  • The roles the user held, and the roles the affected member declares.
  • What you expected, and what happened instead.
  • Your versions of PHP, Symfony, Doctrine ORM, and this library.

What happens next

  • We answer within three working days to confirm that the report arrived.
  • We tell you our assessment within ten working days. That covers whether we accept the report, and what we plan to do.
  • We tell you when a fix is released.

Tell us how you want to be credited. We name reporters in the release notes unless they ask us not to.

Supported versions

This library has no stable release yet. Every version before 1.0 is a development version, and fixes go to the newest one alone.

After the 1.0 release, this section will list the versions that receive fixes.

Scope

The library renders Doctrine entities as JSON API documents and applies request bodies back onto them. Its security surface is the boundary between what a user can reach and what a serializer declares.

In scope

  • A secured attribute or relationship that reaches a response for a user without the role.
  • A query parameter that reveals a secured value without returning it. Sorting, filtering, and pagination can all leak an ordering.
  • A write that reaches a property the serializer does not declare.
  • A write that reaches a secured member without the role, through deserialize() or through an atomic operation.
  • A way past authorizeOperation().
  • An atomic batch that commits part of its work after a failure.
  • A crafted request that raises an unhandled error instead of a 4xx response.

Out of scope

  • The default resolveRelated(). It resolves related entities by id and makes no per-row check, so any caller can attach any existing row of that type. This is documented behavior. Override the method to scope the lookup. Read docs/serializers.md.
  • DQL injection through buildFilter() or buildPagination(). You write those methods. Bind every value as a query parameter.
  • tests/TestApp. It is a demonstration application. It has no authentication, and its development secret is in version control on purpose.
  • A report that needs a serializer to declare a member as public when it holds private data. Declare it with secured().

There aren't any published security advisories