Built-in ID scalar used in output instead of a custom scalar

Issue ID: graphql-data-output-custom-scalar-id-needed

Average severity: Critical

Description

.The schema exposes identifiers using a built-in scalar of the type ID instead of using a domain-specific custom scalar.

For more details, see the GraphQL specification.

Possible exploit scenario

In GraphQL, the built-in ID scalar is defined as a unique identifier serialized as a string. However, this poses several problems:

  • It accepts any string or integer value
  • It has no format or length constraints
  • It carries no semantic meaning
  • It does not express ownership, tenant scope, or domain boundaries
  • It does not enforce structural validation

Identifiers returned by an API are security-sensitive because:

  • They define object-level access targets
  • They enable subsequent mutation or query operations
  • They allow enumeration of resources
  • They reveal correlation patterns across systems
  • They may expose internal database keys or predictable sequences

If a generic ID is used for all entity types, clients cannot distinguish between them. This increases the risk of:

  • Type confusion between identifiers belonging to different domains
  • Cross-entity misuse
  • Broken Object Level Authorization (BOLA) exploitation
  • Enumeration attacks when identifiers are sequential or predictable
  • Leaking of internal database identifiers

In federated GraphQL architectures, this risk increases further: identifiers propagate across subgraphs, and type ambiguity may enable cross-service inconsistencies.

Using domain-specific custom scalars makes identifier semantics explicit and allows enforcing UUID-only formats, length restrictions, prefix or namespace rules, and strongly separated identifier domains. Because identifiers define the primary object-access boundary in GraphQL APIs, misuse or weak modeling of identifiers significantly increases the risk of their exploitation.

Remediation

Replace the built-in ID scalar with a domain-specific custom scalar that carries explicit constraints. We recommend that you:

  • Define a distinct scalar for each identifier domain, such as:
    • UserId
    • AccountId
    • OrderId
    • TenantId
  • Avoid exposing raw database keys
  • Prefer opaque identifiers when possible
  • Enforce strict format and length constraints

Explicit identifier modeling reduces enumeration risk, prevents cross-domain confusion, and improves the robustness of authorization.