You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed by the domain:services PM seat from the #7902 credential-persistence survey (report: comment 5264546868). Unassigned, no pm:queue, no domain:* — see routing note. For triage to grade and route.
The finding
sys_sso_provider.oidc_config is a textarea whose own field description states what it holds:
— packages/platform-objects/src/identity/sys-sso-provider.object.ts:267-272. Read back by the better-auth SSO plugin.
This is shape ① from the survey: a credential inside a serialized JSON blob, on an object reachable through the ordinary data API (sys_sso_provider declares apiMethods: ['get','list']).
An OIDC clientSecret is the credential that authenticates this platform to the identity provider. Anyone who can read the row can impersonate the platform's OIDC client against that IdP.
What makes this one distinctive
Unlike the other ① hits, nothing here is hidden or accidental. The blob is doing exactly what its description says. There is no drift between declaration and behaviour to point at — which means:
the "declared ≠ enforced" framing does not apply; and
fixing it is not a repair, it is a decision to change a shipped storage shape, with migration for existing rows.
That is why it is filed as a finding for grading rather than a defect to dispatch. The card that takes it up has to choose a shape first, and that choice has an owner beyond this lane (below).
Shape of a fix, if wanted (⛔ not decided here)
Same fork as #7986, and for the same reason — a blob with mixed sensitivity:
pull only clientSecret into a Field.secret()-backed column, leaving the rest of the config in the blob (needs a shape change to what authors write);
move the whole oidc_config behind Field.secret() (simple, but the non-secret half becomes unreadable to the admin UI that legitimately renders endpoints/scopes/mapping);
redact on read (leaves cleartext at rest, which is the property the survey is about).
⚠️better-auth owns the writes to this object — the same constraint that makes #7987 (sys_account OAuth tokens) hard. Any shape that routes the write through the engine's encrypt-on-write path has to sit between better-auth and its own adapter. That constraint is the first thing a card should measure, not the last.
Explicitly NOT claimed
No leak is demonstrated. Reachable-cleartext finding; permissions on sys_sso_provider in a shipped deployment were not evaluated.
Not an ADR-0100 case.Field.password() has zero occurrences repo-wide; this is a textarea, not a password-typed field.
The column is declared in packages/platform-objects (domain:metadata); the consumer is the better-auth SSO plugin under plugin-auth (domain:identity); a Field.secret() route touches the objectql machinery (domain:engine-core). Which lane owns it depends on the shape chosen. Flagged rather than guessed, per the anchoring rule — the label is the domain of the package the fix lands in, never the domain of where it was found.
Evidence
Measured 2026-08-12 by the dev on #7902 (read-only survey, pr: null). Full 26-surface verdict table, including the reverse-checks that validate the clean verdicts, in comment 5264546868 on #7902.
Source
Split out of #7902 (survey item ①-e). Sibling cards from the same survey: #7986 (webhook headers), #7987 (sys_account OAuth tokens), #7990 (sys_metadata as a general cleartext sink).
Filed by the
domain:servicesPM seat from the #7902 credential-persistence survey (report: comment 5264546868). Unassigned, nopm:queue, nodomain:*— see routing note. For triage to grade and route.The finding
sys_sso_provider.oidc_configis atextareawhose own field description states what it holds:—
packages/platform-objects/src/identity/sys-sso-provider.object.ts:267-272. Read back by the better-auth SSO plugin.This is shape ① from the survey: a credential inside a serialized JSON blob, on an object reachable through the ordinary data API (
sys_sso_providerdeclaresapiMethods: ['get','list']).An OIDC
clientSecretis the credential that authenticates this platform to the identity provider. Anyone who can read the row can impersonate the platform's OIDC client against that IdP.What makes this one distinctive
Unlike the other ① hits, nothing here is hidden or accidental. The blob is doing exactly what its description says. There is no drift between declaration and behaviour to point at — which means:
That is why it is filed as a finding for grading rather than a defect to dispatch. The card that takes it up has to choose a shape first, and that choice has an owner beyond this lane (below).
Shape of a fix, if wanted (⛔ not decided here)
Same fork as #7986, and for the same reason — a blob with mixed sensitivity:
clientSecretinto aField.secret()-backed column, leaving the rest of the config in the blob (needs a shape change to what authors write);oidc_configbehindField.secret()(simple, but the non-secret half becomes unreadable to the admin UI that legitimately renders endpoints/scopes/mapping);sys_accountOAuth tokens) hard. Any shape that routes the write through the engine's encrypt-on-write path has to sit between better-auth and its own adapter. That constraint is the first thing a card should measure, not the last.Explicitly NOT claimed
sys_sso_providerin a shipped deployment were not evaluated.Field.password()has zero occurrences repo-wide; this is atextarea, not a password-typed field.Routing note — why no
domain:*The column is declared in
packages/platform-objects(domain:metadata); the consumer is the better-auth SSO plugin underplugin-auth(domain:identity); aField.secret()route touches theobjectqlmachinery (domain:engine-core). Which lane owns it depends on the shape chosen. Flagged rather than guessed, per the anchoring rule — the label is the domain of the package the fix lands in, never the domain of where it was found.Evidence
Measured 2026-08-12 by the dev on #7902 (read-only survey,
pr: null). Full 26-surface verdict table, including the reverse-checks that validate the clean verdicts, in comment 5264546868 on #7902.Source
Split out of #7902 (survey item ①-e). Sibling cards from the same survey: #7986 (webhook headers), #7987 (
sys_accountOAuth tokens), #7990 (sys_metadataas a general cleartext sink).