diff --git a/ipa/general/0111.mdx b/ipa/general/0111.mdx index cd80146..4c6c90d 100644 --- a/ipa/general/0111.mdx +++ b/ipa/general/0111.mdx @@ -468,6 +468,326 @@ the server may scale it up or down based on load. } ``` +### Sensitive Fields + +Some resource fields carry secrets — passwords, API keys, private credentials. +The API design **must** prevent accidental exposure of these values in +responses. + + + + + +Sensitive fields **must** be marked in OpenAPI so that consumers and tooling can +identify them (see [IPA-117](0117.mdx#sensitive-field-markings) for the required +annotations). + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + displayName: + type: string + key: + type: string + format: password + writeOnly: true +``` + + + The `key` property carries `format: password` and `writeOnly: true`, so + tooling and reviewers know the field contains a secret and must not appear in + responses. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + displayName: + type: string + key: + type: string +``` + + + The `key` property lacks any annotation — no `format: password`, no + `writeOnly` — so neither consumers nor tooling can tell that the field carries + a secret. + + + + + + + Identify fields that carry secrets — passwords, API keys, credentials, or + other sensitive material. + + + For each sensitive field, confirm it carries an OpenAPI annotation (e.g. + `format: password`, `writeOnly: true`) that marks it as sensitive. + + + Report sensitive fields that have no marking or rely only on naming + conventions. + + + + + + + + + +Sensitive fields **must** follow one of the following information-flow patterns: + + + + + +**Write-only.** The client submits the value on [Create](0106.mdx) or +[Update](0107.mdx) and the server **must not** return it in any response. + + + + + +```yaml +components: + schemas: + ApiKeyCreate: + type: object + properties: + displayName: + type: string + key: + type: string + format: password + writeOnly: true +``` + + + The `key` is write-only — the client sends it on create, and the server never + returns it in subsequent Get or List responses. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + displayName: + type: string + key: + type: string +``` + + + The `key` is not marked write-only, so the client expects it to appear in + responses — leaking the secret. + + + + + + + Identify fields whose value is submitted by the client and must not be + returned. + + + Confirm each such field is marked `writeOnly: true` and does not appear in + response schemas. + + + Flag any write-only field that appears in a response schema. + + + + + + + + + +**Reveal-once.** For values the client cannot retrieve later (e.g. +server-generated API keys), the field **may** appear in the [Create](0106.mdx) +response so the client can capture it, but **must not** appear in subsequent +[Get](0104.mdx) or [List](0105.mdx) responses. + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + id: + type: string + displayName: + type: string + key: + type: string + format: password + writeOnly: true +``` + + + The `key` appears only in the Create response — the client captures it once. + The `writeOnly` declaration prevents it from appearing in Get and List + responses. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + id: + type: string + displayName: + type: string + key: + type: string + format: password +``` + + + The `key` lacks a `writeOnly` declaration, so the schema allows it to leak in + every Get and List response. + + + + + + + Identify fields that are server-generated and shown only once (e.g., initial + API key secret). + + + Confirm the field appears only in the Create response schema and is marked + `writeOnly` to exclude it from Get and List responses. + + + Flag any reveal-once field that appears in Get or List response schemas. + + + + + + + + + +When a masked representation of a sensitive field (e.g. `****` or a last-4 +display value) needs to appear in [Get](0104.mdx) or [List](0105.mdx) responses, +it **must** be modeled as a separate read-only **redacted sibling** property +following the [Effective Values](#effective-values) pattern. The raw and +redacted values **must not** share the same property name. A redacted sibling +**may** be added to either a write-only or a reveal-once field independently of +the chosen information-flow pattern. + + + + + +A masked display of a sensitive field (e.g. `****` or a last-4 display value) +**must** be modeled as a separate read-only **redacted sibling** property, not +reusing the raw field's name. + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string + format: password + writeOnly: true + keyRedacted: + type: string + description: Last four characters of the API key. + readOnly: true +``` + + + The raw value is `key` (write-only); the masked display is `keyRedacted` + (read-only, last-4 display). They are distinct properties with different + names, so no ambiguity exists about which carries the secret. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string +``` + + + A single property named `key` cannot simultaneously be write-only and carry a + masked display. Consumers cannot tell whether the value is the raw secret or a + redacted version. + + + + + + + Find fields whose response value is a masked or truncated display of a + secret (e.g. `****`, last-4). + + + Confirm the masked value lives on a separate property with a distinct name + (e.g. `keyRedacted`) rather than replacing the raw field. + + + Report any field that mixes a raw secret and a masked display under the same + property name. + + + + + + + + + ### Boolean Values diff --git a/ipa/general/0117.mdx b/ipa/general/0117.mdx index 09322d6..05fc0b6 100644 --- a/ipa/general/0117.mdx +++ b/ipa/general/0117.mdx @@ -673,6 +673,157 @@ properties: +### Sensitive Field Markings + +The OpenAPI `format: password` keyword identifies properties whose value is +itself a secret. Guidelines below govern when to apply it. + + + + + +**Must use** `format: password` on any property whose value is itself a secret +per [IPA-111 — Sensitive Fields](0111.mdx#sensitive-fields). + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string + format: password + writeOnly: true +``` + + + The `key` property carries a secret value (an API key), so `format: password` + marks it as a secret for tooling and consumers. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string + writeOnly: true +``` + + + The `key` is write-only but lacks `format: password`, so tooling cannot + distinguish it from any other write-only string field. + + + + + + + Identify all properties that carry a secret value per IPA-111. + + + Confirm each such property sets `format: password` in its schema. + + + Report secret-carrying properties that omit `format: password`. + + + + + + + + + +**Must not** use `format: password` on a redacted sibling property whose value +is a masked display (`****`, last-4 digits, etc.). The redacted value is not +itself a secret; marking it as such misleads consumers and tooling. + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string + format: password + writeOnly: true + keyRedacted: + type: string + description: Last four characters of the API key. + readOnly: true +``` + + + Only the raw `key` carries `format: password`. The redacted sibling + `keyRedacted` carries a masked display, not a secret, so it omits the format. + + + + + + +```yaml +components: + schemas: + ApiKey: + type: object + properties: + key: + type: string + format: password + writeOnly: true + keyRedacted: + type: string + format: password + description: Last four characters of the API key. + readOnly: true +``` + + + `keyRedacted` is a masked display whose value is not a secret — it repeats a + few characters the consumer already provided. Marking it with `format: + password` misleads tooling into treating the redacted value as a secret. + + + + + + + Identify redacted sibling properties — read-only fields that show a masked + or truncated display of a sensitive field. + + + Confirm none of these sibling properties carries `format: password`. + + + Report redacted siblings that are incorrectly marked with `format: + password`. + + + + + + + + + ### Examples