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

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

Average severity: High

Description

The schema exposes numeric values using a built-in scalar of the type Int in an output position instead of a domain-specific custom scalar.

For more details, see the GraphQL specification.

Possible exploit scenario

Numeric built-in scalar types Int and Float can handle basic data validation. While it ensures that the value is numeric and within a technical range (for example, between −2³¹ and 2³¹−1), they do not express the constraints that matter for application security and robustness, such as:

  • Allowed range (min and max):
    • Prevent extreme values that could cause logic errors or overflows (for example, in prices, quantities, latitude or longitude)
    • Prevent extreme values that could trigger expensive processing paths (such as extreme values used in filtering, ranking, or scoring)
  • Minimum or maximum business constraints
  • Domain semantics distinguish between conceptually different numbers (like price, percentage, latitude, weight) so that they do not get reused incorrectly
  • Contextual usage rules

In real-world APIs, integers frequently represent:

  • Pagination parameters (limit, offset, page)
  • Quantities (quantity, count)
  • Status codes
  • Ranking or scoring values
  • Index-based object access
  • Privilege levels or role indicators

Using unconstrained Int in output position can lead to:

  • Information disclosure (such as revealing internal counts or system capacity)
  • Enumeration signals (such as sequential numeric identifiers)
  • Unexpected extreme values due to logic flaws
  • Contract instability if ranges change between versions
  • Downstream client assumptions that are not formally guaranteed

For example, returning a raw integer counter without bounds may leak internal system scale or enable inference of business-sensitive information.

Using a custom scalar — typically paired with validation directives such as @numberValue(min:, max:) or an equivalent mechanism — makes output semantics explicit and allows enforcing:

  • Defined value ranges
  • Business-meaningful limits
  • Clear differentiation between numeric domains
  • Stronger contract stability

Remediation

Replace built-in Int in output positions with domain-specific constrained scalars.

We recommend that you:

  • Define specific scalars for numeric domains
  • Avoid exposing raw sequential numeric identifiers
  • Enforce consistent minimum and maximum bounds across services and subgraphs

Explicit numeric modeling improves contract clarity, reduces unintended data disclosure, and makes the API definition more robust.