Field-Level Data Obfuscation for GraphQL | Cosmo by WunderGraph - WunderGraph

Mask sensitive GraphQL fields by role, without touching subgraphs

Cosmo Router Custom Modules let you intercept and obfuscate GraphQL response fields at the router level. Different users see different data. No subgraph code changes.

Written in Go. Field-level. Applied per request.

The problem

The same API serves users who should see different data

Field-level access control is real work. Doing it in every subgraph is fragile and expensive to maintain.

Different users need different data visibility

A developer debugging a query should not see real customer names or payment data. A data scientist needs realistic data shapes but not the actual PII. The same API serves both.

Subgraph-level masking requires code changes everywhere

Adding field-level obfuscation in each subgraph means touching every service, syncing release cycles, and maintaining that logic as schemas evolve.

AI systems should not read sensitive fields

When GraphQL APIs are exposed to AI models or third-party systems, fields like SSNs, credit card numbers, and medical data must be protected without duplicating the API.

Our solution

Field-level obfuscation at the router

A Custom Module intercepts GraphQL response data before it reaches the client. The renderer replaces field values based on user role or request context. Subgraphs are unaware of the transformation.

How it works

  1. Implement a CustomFieldValueRenderer interface in a Cosmo Router Custom Module, written in Go.
  2. The renderer receives each field value with its GraphQL type (String, Int, Float, or custom) and can transform or replace it.
  3. Use the RouterOnRequest hook to select different renderers based on authentication claims, user roles, or request headers.
  4. A developer with the "developer" role gets all String fields replaced with "xxx" and numeric fields with placeholders, preserving the response structure.
  5. An AI system identified by a specific header receives placeholder values for any field marked sensitive, while the rest of the response is unaffected.
  6. No subgraph code changes are required. The obfuscation layer lives entirely at the router.

Before & After

Before Cosmo With Cosmo
Data masking implemented separately in each subgraph Centralized obfuscation at the router, applied to all subgraphs
Complex authorization logic in every resolver Role-based obfuscation via authentication claims and request context
Separate data pipelines for AI and analytics access Same API with dynamic field filtering per request context
Code changes required to add or change privacy rules Custom Module update without touching subgraph implementations

Field value renderer interface

func (c *CustomValueRenderer) RenderFieldValue(
  ctx *resolve.Context,
  value resolve.FieldValue,
  out io.Writer,
) error {
  switch value.Type {
  case "String":
    _, err = out.Write([]byte(`"xxx"`))
  case "Int", "Float":
    _, err = out.Write([]byte(`123`))
  default:
    _, err = out.Write(value.Data)
  }
  return err
}

How field-level obfuscation works in Cosmo Router

01

Intercept

The router processes the GraphQL response from subgraphs before sending it to the client. The Custom Module intercepts each field value at this point.

02

Identify

The RouterOnRequest hook reads authentication claims, user roles, or request headers to determine which renderer to apply for this request.

03

Transform

The CustomFieldValueRenderer receives each field with its type information and writes the obfuscated value. String fields become "xxx"; numeric fields become placeholder values.

04

Return

The client receives a structurally complete response. Types, field names, and nesting are preserved. Only the values that match the obfuscation rules are replaced.

Fine-grained control at the gateway

Centralized privacy control

Implement obfuscation once at the router. All subgraphs behind it inherit the protection without any code changes.

Role-based obfuscation

Apply different rendering rules per request based on authentication claims, user roles, or any request context your Custom Module can read.

AI-safe API access

Protect sensitive fields when exposing your GraphQL API to AI models or third-party integrations. The model gets realistic response shapes with placeholders for protected fields.

No subgraph changes

Add, change, or remove privacy rules by updating the Custom Module. Subgraph code and schemas stay untouched.

Add field-level privacy to your GraphQL API

Implement a Custom Module renderer. Apply it at the router. Subgraphs stay unchanged.

FAQ

Advanced data privacy on Cosmo Router

Full implementation guide in the advanced data privacy documentation.