Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Inline-editing a password / secret field on the detail page renders the mask as the value and writes it straight back #4221

Closed

Description

@yinlianghui

Filed unassigned per Prime Directive #10, from the fall-through sweep for #4216. Split out from #4220 (the rest of that sweep) because the severity and the argument are different: this one writes a masked placeholder into a credential field.

What happens

packages/plugin-detail/src/InlineFieldInput.tsx has no branch for password or secret, so both reach the terminal raw text input at the end of the component. The detail hosts' editability gate (DetailSection / HeaderHighlight) excludes only readonly, computed and system fields, so neither type is held back: the pencil / double-click affordance appears on a credential field.

Both types are masked on read. The value the cell holds is therefore a placeholder, not the secret — so the inline editor seeds a plain text box with the mask, shows it in clear as if it were the current value, and saves it back verbatim if the user commits the row.

This decision is already written down, one package over

@object-ui/fields excludes both from in-place editing and gives exactly this reasoning — INLINE_EXCLUDED_FIELD_TYPES in FieldEditWidget.tsx:

Credentials — never inline-editable. Both are masked on read, so the cell has no real value to seed an editor with, and the grid's fallback is a PLAIN TEXT input: it would render the mask as if it were the value and write it straight back. secret additionally round-trips through an encrypted store (ADR-0100, data/field.zod.ts) — the cell holds an opaque ref, not the secret.

The grid honours that set. InlineFieldInput never consults it, so the detail page reproduces the exact failure the set exists to prevent — including, for secret, writing a mask over what should be an opaque reference into an encrypted store.

Why it is not "just" a corrupted field

Two distinct harms beyond the overwrite:

  1. Disclosure shape — the mask is rendered in a type="text" input, so whatever the mask contains is displayed in clear and is selectable/copyable, in a control the user believes holds their credential.
  2. Silent credential loss — committing the row replaces a working secret with the placeholder, and nothing in the flow says so. The failure surfaces later, wherever that credential is used.

Likely shape of a fix

Make both non-editable inline on the detail path, by the same rule the grid uses — have the hosts' editability gate consult isInlineExcludedFieldType() from @object-ui/fields rather than growing a second hand-maintained list. Pin it: a password and a secret field must render no inline-edit affordance and must not produce an editor. Re-authoring a credential belongs in the record form, which has the widget for it (PasswordField).

Related: #4220 (the remaining fall-through classes and the FieldEditWidget duplication behind all of them), #4219 (autonumber slipping the computed gate), #4216 (the object-valued composites).


Generated by Claude Code

Activity

  1. self-assigned this
    on Aug 11, 2026
  2. yinlianghui commented on Aug 11, 2026

    @yinlianghui
    ContributorAuthor

    CLAIM (objectui whole-repo seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3) — graded queue+bug on filing (credential loss + disclosure shape) and dispatching a dev agent now.


    Generated by Claude Code

  3. yinlianghui commented on Aug 11, 2026

    @yinlianghui
    ContributorAuthor

    ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4228. Held at draft (fourth in the hold queue behind the train-finisher): its three CI reds are the pre-existing main fallout, proven twice over, with the dev's own tests green inside CI's shards.

    The wiring is the card's shape exactly — one helper in the shared fieldEnrichment module delegating to isInlineExcludedFieldType() (the grid's contract, alias-aware, narrow-only union mirroring the #3355 pattern), one conjunct added per host, zero new lists. The premise refinement matters and is recorded: the editor seeds from the PAYLOAD value, not the mask renderer — for secret the clear-text box was showing the ADR-0100 encrypted-store reference itself. The blast-radius table is measured on-branch with the gates reverted, and its hard case was handled with exactly the right instrument: the six binary/media types are EXEMPTED because InlineFieldInput genuinely routes them, with each exemption pinned twice (real member of the shared set AND really rendering a non-terminal editor) so an exemption that outlives its routing fails the suite — the anti-drift invariant this whole family needed.

    Delegated ruling on the open question (veto window open): A, as shipped — markdown/html/richtext stay excluded. A one-line type="text" box over a multi-paragraph document is a truncation path, not a working editor; exempting them would admit the only entry NOT backed by a real widget, breaking the invariant that makes the exemption trustworthy. If there is pull for real inline editors for those types, that is #4220's routing-design half.

    Cross-card effects, recorded: the CONTAINER half of #4220 is closed here (pinned no-longer-editable) — #4220 re-scopes to arrays + the type-lossy scalars inside the set's "editable" verdict + the delegate-vs-route ruling. #4219's user-facing defect (inline-editable autonumber) appears CLOSED by the alias resolution — the seat will verify and close it rather than dispatch. The serialization judgment (30 min of polling, then measured file-disjointness, then a mid-run rebase onto the landed #4222 with its types pinned as controls) is the discipline applied with sense rather than ritually. CI colour context: read against #4231.


    Generated by Claude Code

  4. added a commit that references this issue on Aug 17, 2026
    5e2e9fa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions