Skip to content

bug: credential secrets, SSL private keys, and plugin tokens are displayed in plaintext in view mode #3416

Description

@moonming

Issue description

Sensitive values are rendered in plaintext across the dashboard's read paths. The masking added in d32c945 covers only the secret-manager forms (Vault token, AWS keys, GCP private key) and the Settings admin-key field; the most common credential paths are unprotected:

  1. Consumer credential secrets — a key-auth key, basic-auth password, jwt-auth secret, hmac-auth secret_key are fully visible: open the credential's detail page → the plugin card's View drawer shows e.g. {"key": "SUPER-SECRET-KEY-12345"} verbatim in the Monaco editor, in read-only view mode, with zero interaction needed beyond opening the card. (Verified live on master 9979b31.) Path: FormPartCredential.tsxFormItemPluginsPluginEditorDrawer — no masking concept exists anywhere in the Monaco render path.
  2. SSL private keys — the SSL detail page renders key / keys[i] through FormItemTextareaWithUpload, a plain textarea showing whatever the Admin API returns, unmasked, expanded via autosize in view mode (FormPartSSL/FormItemCertKeyList.tsx).
  3. Plugin configs containing tokens — any plugin whose config embeds secrets (ai-proxy/ai-proxy-multi API keys, limit-* redis_password, logger auth headers, forward-auth, …) displays them verbatim in the same editor drawer on routes/services/global rules detail views.
  4. Transient echo in error toasts — the interceptor toasts raw Admin API error bodies (error_msg), which for schema-validation failures can include the submitted secret value (src/config/req.ts).

Expected behavior

  • In view mode, known-sensitive JSON paths are redacted by default ("key": "•••••") with an explicit reveal affordance, mirroring how FormPartSecret already treats vault/aws/gcp fields.
  • SSL private key fields use a masked control in view mode (certs can stay plaintext).
  • Error toasts truncate long bodies rather than echoing full submitted payloads.

Suggested implementation

Maintain a small per-plugin sensitive-path registry (key-auth.key, basic-auth.password, jwt-auth.secret, hmac-auth.secret_key, ai-proxy.auth.*, *.redis_password, …) and apply it as a display-transform in PluginEditorDrawer's view mode before handing the JSON to Monaco. Edit mode can stay unmasked (an editor must show what it edits), which still removes the shoulder-surfing/screen-share exposure from the default read path.

Environment

  • apisix-dashboard: master (9979b31)

Related: #3218 (the original report; this issue records the verified residual scope after d32c945)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions