Skip to content

fix: keep stored secrets out of form HTML (A20) - #124

Merged
coderbuzz merged 2 commits into
mainfrom
fix/secrets-in-forms
Oct 16, 2026
Merged

coderbuzz merged 2 commits into
mainfrom
fix/secrets-in-forms

Conversation

@coderbuzz

Copy link
Copy Markdown
Owner

Audit finding A20 (pre-revamp): stored secrets were rendered into page HTML.

  • Settings → Webhook secret: no longer in the page. Show/Copy load it once from the existing authenticated GET api/settings/webhook-secret; Roll unchanged.
  • App edit → Basic auth password: input is empty with placeholder unchanged. Empty keeps the stored password; a new value replaces it; an empty Username removes basic auth (and clears the password). Hint text says so. The add form still echoes the just-typed value on a validation error (user input, nothing stored yet).
  • App edit → secret env vars: sent as {value:"", masked:true, orig:KEY}. The form posts env_orig per row; saveFormEnvVars keeps the stored value for an untouched masked row, also when the row was renamed or switched to plain (on main both of those wiped the value). Export in the env card fetches masked values from GET api/apps/{id}/secrets only when clicked.
  • JSON API unchanged.

Evidence:

  • TestSecretsNotInFormHTML (fails on main with 9 errors, passes here): /settings and /apps/{id}/edit HTML contain neither the webhook secret, the auth password nor secret env values; edit with empty password keeps it; rename / make-plain of masked rows keeps values; removed row deleted; new password replaces; empty username clears auth.
  • Browser (mock, 18090): Show reveals the secret, Copy puts it on the clipboard, edit page placeholders unchanged, Export shows real values, Save without changes keeps auth_pass and secrets (checked via API), no pageerror.
  • go build ./... && go vet ./... && go test ./... OK; tests/e2e/ui.mjs PASS.

🤖 Generated with Claude Code

coderbuzz and others added 2 commits October 16, 2026 07:45
Settings loads the webhook secret from the API on Show/Copy. The app edit form gets an empty
basic-auth password (empty keeps it, empty username removes auth) and secret env values masked
(empty + original key); the handler keeps the stored value unless it is changed, also when the
row is renamed or made plain. JSON API unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…e could be overwritten)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@coderbuzz

Copy link
Copy Markdown
Owner Author

Opus review (read-only, go test/vet green): no blocking findings. Confirmed: no stored secret reaches HTML (incl. error re-renders), clients without env_orig fall back to the old keep-empty-secret rule, rename/swap safe (existing snapshot), no XSS in new JS, JSON API and add form unchanged. Optional: (1) renaming a row onto an existing key loses one value — fixed in the follow-up commit (validateForm rejects duplicate keys, 400, tested); (2) clearing the password no longer disables auth (fail-safe, hint added); (3) API client renaming a masked row without env_orig; (4) masked→plain shows value afterwards (intended); (5) Safari Copy may need a second click; (6) username without password = no auth (pre-existing).

@coderbuzz
coderbuzz merged commit e757276 into main Oct 16, 2026
@coderbuzz
coderbuzz deleted the fix/secrets-in-forms branch October 16, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant