How Stubsmith never sees your cleartext data

A security architecture deep-dive: how edge-side masking ensures Stubsmith's servers never receive raw API payload values, and what that means for your GDPR posture.

A fixture service is, at its core, a copy of your API traffic. That framing is also the right one for evaluating any vendor’s privacy claim about one. Before reaching for a tool that generates stubs from real request/response pairs, ask the question directly: does the vendor’s server ever see my payload content? If the answer is anything other than a structural “no”, enforced by where masking runs rather than by an access policy, you are trusting the vendor with production data.

This document covers Stubsmith’s architecture at the level a security reviewer would forward to a data protection officer. It explains what happens in each zone of the data flow, what crosses your network boundary, what Stubsmith’s server can and cannot do with what it receives, and what this means for your obligations as a data controller.

The threat model

Start with what goes wrong in a naive fixture service.

A developer captures a real API response and commits it to a test fixture file. It contains PII. Now it’s in version history, accessible to everyone with repository access, outside the data retention and access controls that govern production. This is the cassette problem described in any honest comparison of record-and-replay tools: the default is to record everything, filtering is opt-in, and filter rules fail open.

A fixture service that captures traffic server-side, in its own infrastructure, is a different shape of the same problem. The vendor promises to mask sensitive fields. You are trusting a policy promise, implemented in their code, running on their servers. A misconfiguration, a staff action, or a breach can expose payload content. Even if the vendor applies server-side at-rest protection, the server held the plaintext briefly before applying it.

Stubsmith’s architecture is designed so that neither scenario applies, because masking happens before anything leaves your infrastructure.

The edge boundary

Stubsmith’s SDK operates as middleware inside your own service’s process. When a request/response pair is captured, two things happen inside your infrastructure before any network call is made:

Your infrastructure
┌────────────────────────────────────────────────────┐
│                                                    │
│  API service  ──►  Stubsmith middleware            │
│                    │                               │
│                    └─ Anonymizer rules applied     │
│                          (mask / redact values,    │
│                           fail-closed)             │
│                                                    │
└────────────────────────────┬───────────────────────┘

                 masked body + structural fingerprint


              Stubsmith ingest endpoint
              (receives masked values and field names only)

Masking removes sensitive content while preserving structure. This step executes in your process, on your hardware or your cloud instances, under your network perimeter. No raw payload values cross the boundary between your infrastructure and Stubsmith’s.

This is the core guarantee. It is structural, enforced by where masking runs, not a policy that could be modified by a configuration change on Stubsmith’s servers.

What actually leaves your network

Two things cross the boundary:

Masked sample bodies. The request/response body after anonymizer rules have run. Values are replaced with typed placeholders: strings become "<masked>", numbers become 0, booleans become false. With the opt-in format-preserving mode (STUBSMITH_MASK_SALT), string placeholders keep their shape (a masked email is still a syntactically valid email, a masked UUID is still a valid UUID), but the value is derived from a keyed hash of the original, not the original itself. Either way, Stubsmith’s server stores the masked body. The values your users sent or your API returned are not present in what we receive.

Structural fingerprints. A fingerprint is the structural signature of the request/response pair: HTTP method, path pattern, and response schema shape. It contains no payload data. Fingerprints are how Stubsmith deduplicates traffic: two requests with the same method, path, and response structure produce the same fingerprint and are grouped under one canonical fixture rather than stored as near-identical copies. Your endpoint names, HTTP methods, and response schema shapes are visible in fingerprints. The values, meaning what your users sent or what your API returned, are not.

Shape-preserving masking semantics

The anonymizer runs your masking rules over the payload. The masking semantics are deliberately conservative: masked values keep their structural shape but lose their content.

  • String fields are replaced with "<masked>".
  • Numeric fields become 0.
  • Boolean fields become false.
  • Null fields remain null.

The point of shape-preserving masking is that the resulting stub still generates valid test behavior. A payment amount replaced with 0 still occupies the correct field at the correct type position in the response. A name field replaced with a placeholder still causes your parser to allocate a string of roughly that size. The fixture is usable for testing; the value is not useful to anyone who intercepts or reads it.

For cases where type shape alone is not enough, Stubsmith also supports format-preserving placeholders. When STUBSMITH_MASK_SALT is set at the capture point, a masked email becomes a syntactically valid email, a masked UUID becomes a different valid UUID, and a masked IBAN carries a correct mod-97 checksum. The placeholder is derived from a keyed hash of the original value, so it is deterministic and the same input always produces the same placeholder. This is opt-in; the constants above remain the default. Low-cardinality types such as currency_code, country_code, and booleans always use constant placeholders regardless of the salt setting, because a keyed hash over a small value space is recoverable from a lookup table.

Masking is content removal with shape retention. The shape is retained because that is what stub generation requires; the content is removed because that is what privacy requires. Raw values are absent from what Stubsmith receives, not because a key is missing, but because masking already ran. The result is realistic fixtures that contain no cleartext sensitive data.

Fail-closed defaults

Any masking system has an obvious failure mode: a new field appears in an API response, it isn’t covered by a masking rule, and it passes through unmasked. The default behavior when that happens matters.

Stubsmith’s defaults are designed to fail closed. When the system encounters a situation where it cannot safely determine how to handle a payload (an unknown response structure, an ambiguous rule application), it drops the sample rather than ingesting it with unknown content. The conservative path is always to reject or mask more aggressively, not to pass through and handle it later.

Fail-closed defaults change the failure mode from a silent data leak to a visible operational event. An over-aggressive mask produces stubs that fail in test because a field is missing or zero; that failure is immediately visible to the developer and fixable. A silent data leak produces nothing visible until an audit or an incident. The first failure mode is cheaper.

The practical implication: when you add a new third-party integration or an upstream API starts returning new fields, update your masking configuration before enabling capture for that endpoint. The fail-closed defaults give you a safe interim: new unrecognised shapes are dropped rather than recorded.

What Stubsmith stores

Stubsmith stores two kinds of data on its servers:

Masked sample bodies. Request and response bodies after masking rules have run. Values have been replaced; types and structure are preserved. The amount field is 0. The name field is "<masked>". The email field is "<masked>" (or a keyed-hash-derived email at your placeholder domain if format-preserving masking is enabled). This data is useful for stub generation; it does not contain your users’ personal data.

Structural fingerprints. The key-paths, HTTP method, path pattern, and content type that characterise the request/response shape. No values. Fingerprints are how Stubsmith deduplicates traffic and organises stubs. They are visible to Stubsmith staff: if your API path encodes sensitive information (e.g. /users/{email}/profile), that structure is visible.

GDPR posture: Stubsmith as a processor that cannot read content

Under GDPR, a vendor that processes personal data on behalf of a controller is a data processor and requires a Data Processing Agreement. The key question for your DPA analysis is whether Stubsmith actually processes personal data, meaning whether the server has access to content that identifies or relates to an individual.

The edge-masking architecture is designed so that Stubsmith’s server stores only already-masked payloads. If masking rules are correctly configured, no personal data crosses the boundary in the first place. The masked body that arrives at the ingest endpoint was produced from a payload from which personal data had already been removed.

The structural fingerprint that accompanies the body contains schema shape and path structure, not personal data under any normal interpretation. Metadata of that kind may be commercially sensitive, but it is not personal data that triggers GDPR obligations on Stubsmith’s end.

This substantially limits Stubsmith’s role as a processor compared to any service that receives plaintext payloads. The architecture is designed so that “processor” is a technical stretch: the server holds masked bodies (with values replaced) and structural metadata about your API shape, not payload content it could act on.

Honest limits

Edge masking is a strong control. It is not an absolute guarantee. A security reviewer should understand what it does not cover.

Misconfigured masking rules. If your masking configuration doesn’t cover a field containing personal data, that field passes through unmasked to Stubsmith’s servers. Fail-closed defaults reduce the blast radius; they don’t substitute for correct configuration. Reviewing masking rules when the upstream API adds fields is operational hygiene, not optional.

Metadata visibility. Endpoint paths, HTTP methods, and response schema shapes are visible to Stubsmith in fingerprints. If your API path structure encodes sensitive information, /users/{email}/profile for example, that structure is visible. Fingerprint data is structural metadata about your API, not payload content, but it is visible to Stubsmith.

Your own infrastructure scope. The edge boundary is the boundary of your infrastructure. Masking happens before transmission, inside your perimeter. The security of that perimeter (access to the host running the middleware, to the SDK configuration, to the masking rule definitions) is your responsibility. Stubsmith’s server-side controls operate on what arrives after masking; they do not compensate for an insecure deployment environment.

The SDK is open source and the masking path is auditable. A third-party security audit is on Stubsmith’s roadmap before the first Business-tier customer signs. All infrastructure runs in the EU; no data is processed by US-headquartered cloud providers.

For teams beginning a formal evaluation, see pricing for plan details. The free tier is available without a card.

Privacy-safe fixtures from real traffic

Mask at the edge, capture once, replay forever in CI.