Skip to content

fix(server): report a secret on a mirrored pane as entered only after herdr took it, and press Enter as a key - #263

Merged
devswha merged 2 commits into
mainfrom
fix/mirror-secret-result
Oct 1, 2026
Merged

devswha merged 2 commits into
mainfrom
fix/mirror-secret-result

Conversation

@devswha

@devswha devswha commented Oct 1, 2026

Copy link
Copy Markdown
Owner

What was wrong

On a terminal that is mirrored (a PC whose herdr cannot terminal attach, as on Windows), entering a password from the secret prompt was reported as done the moment the server handed it over, before herdr had taken it. If herdr refused the send, the browser still showed success and cleared the field. Enter was also sent as a carriage return inside the text, not as a key.

What changed

  • server/index.ts, the secret case: on a mirrored pane the secret goes out as pane.send_text (the secret only), then pane.send_keys ["Enter"], both awaited inside the pane's existing serialized turn. secret-result ok:true is sent only after both; a failure answers ok:false with secret_failed, and no herdr message is forwarded, so the secret cannot leak through an error text.
  • A pane with a real attach is untouched: it still gets pty.write and no RPC payload.
  • The secret is still never queued or kept: a busy pane is refused as before.

Tests and QA

server/secret.contract.test.ts gains two cases that run the real server with terminalAttach: false behind a pass-through proxy socket in front of the test herdr, which records every request and can refuse pane.send_text:

  • accepted: herdr receives pane.send_text "fixture-value" then pane.send_keys ["Enter"]; secret-result ok:true arrives after herdr answered both; the no-echo stand-in records the line.
  • refused: secret-result is ok:false, code: secret_failed, no Enter is pressed, nothing reaches the stand-in.

Before the fix both failed (one send_text carrying fixture-value\r, no send_keys, ok:true before any answer, and ok:true on a refused send). After it: 3 pass, 0 fail, the existing direct-attach case included. bun run typecheck, bun run test:unit (681 pass) and bun run build are green.

Limits

Closes #259

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
CONTRIBUTING.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: devswha/herdr-web-ui/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 4e7346a5-cfc9-4933-a5f3-65e77f062d26

📥 Commits

Reviewing files that changed from the base of the PR and between 94f54b3 and b023336.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • server/index.ts
  • server/secret.contract.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Fixed secret entry in mirrored terminals so success is reported only after the terminal accepts the secret and the Enter key. If the terminal refuses the secret, the submission is reported as failed, and Enter is not sent. Directly attached terminals continue to submit secrets as before.

Walkthrough

Mirrored-pane secret entry now sends the secret text and Enter through separate herdr requests. The server reports success after both requests complete and reports failure if the text send is refused. Direct-attach panes continue to write the secret and carriage return to the PTY.

Changes

Mirrored secret delivery

Layer / File(s) Summary
Mirrored secret RPC delivery
server/index.ts, CHANGELOG.md
Mirrored panes send the secret text and Enter as separate awaited herdr requests. Direct-attach panes retain the PTY write. The changelog records the behavior.
Mirrored secret contract tests
server/secret.contract.test.ts
A herdr proxy records requests and can refuse text sends. Tests check successful request order and results, refusal behavior, and that frames do not expose the secret.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: yoonwoo-ha

Merge Risk: ⚪ Minimal · up to b0233

Mirrored secret submission now waits for text and Enter delivery before reporting success and safely reports failures. Direct-attached panes retain their existing behavior. The change is mergeable with normal checks; real-Windows validation remains unreported.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b0233

The change improves success reporting and preserves existing access checks. No introduced secret disclosure was established. Recovery remains uncertain if the password reaches the terminal but Enter fails or its completion is unknown.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed delivery operation targets the pane already attached to the submitting interactive client. Inspected initiation checks do not expand the operation to additional panes or establish newly gained authority.

Trust Boundaries and Controls

  • observed — The newly identified socket entrypoints belong to a test-local proxy and helper. They use temporary test resources and a loopback server, capture fixture requests, and perform cleanup; they do not introduce a production listener.

Resilience and Maintainability Implications

  • inferred — Pane serialization orders the two requests but does not make them atomic. If text is accepted and Enter fails or times out, secret_failed does not establish that terminal input is empty or that remote execution stopped. There is no compensating clear in this handler. Earlier mirrored delivery also lacked confirmed completion, and the browser's manual-check warning limits unsafe replay; increased exposure remains unproven.

Hardening Proposals

  • proposed — Define and validate provider behavior for accepted text followed by Enter refusal, lost responses and interrupted connections. Consider distinguishing partial or unknown completion from refusal before delivery, while preserving generic secret-safe errors and avoiding automatic replay.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the problem, the resulting behavior, test coverage, validation results, and known limits. It uses different headings from the template, but it includes the required in…
Title check ✅ Passed The title clearly identifies the mirrored-pane secret handling fix, delayed success reporting, and separate Enter key action. It is somewhat long but remains specific and relevant.
Linked Issues check ✅ Passed Issue #259 requires mirrored-pane secret handling to report success only after the text and Enter sends complete, to send Enter with pane.send_keys(["Enter"]), and to report secret_failed without …
Out of Scope Changes check ✅ Passed The changes stay within issue #259. server/index.ts changes mirrored-pane secret delivery. server/secret.contract.test.ts adds tests for the required success and refusal behavior while retaining t…
Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@devswha
devswha merged commit e0ce717 into main Oct 1, 2026
11 checks passed
@devswha
devswha deleted the fix/mirror-secret-result branch October 1, 2026 12:01
devswha added a commit that referenced this pull request Oct 1, 2026
Release v0.3.40: moves the Unreleased notes under 0.3.40 and bumps
`package.json` and `herdr-plugin.toml`.

What's in it:
- Fixes from #249, #251, #252, #263, #264, #265, #267.
- The iPhone CJK and text-symbol fix (#272).
- Emoji cell widths matching herdr (#273).

Every changelog entry already ends with its PR link. All these PRs are
by @devswha, so no credits to add.

No remote bundle change: `REMOTE_BUNDLE_VERSION` stays 9. The Windows PC
part of #264 and #265 reaches a PC with the next remote bundle, as its
changelog entry says.
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.

Secret entry on a mirrored pane reports success before the secret is sent, and sends Enter as \r text

1 participant