Skip to content

fix: harden ProxyCommand SSH config parsing and validation#1118

Merged
GT-610 merged 3 commits into
lollipopkit:mainfrom
GT-610:proxycommand-continue-fix
Apr 10, 2026
Merged

fix: harden ProxyCommand SSH config parsing and validation#1118
GT-610 merged 3 commits into
lollipopkit:mainfrom
GT-610:proxycommand-continue-fix

Conversation

@GT-610
Copy link
Copy Markdown
Collaborator

@GT-610 GT-610 commented Apr 10, 2026

Continue fix of #1117.

Summary by CodeRabbit

  • New Features

    • Improved SSH import validation with clearer user-facing messages for proxy configuration conflicts and prioritization of explicit proxy commands over jump hosts.
  • Bug Fixes

    • SSH parsing now preserves quoted values and trims inline comments only when appropriate.
    • Invalid host entries are skipped with a warning instead of aborting the entire import.
  • Tests

    • Added tests covering inline-comment, quoting, and escape edge cases in SSH config parsing.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aa8d6285-fc55-45d8-b812-438ec86b647a

📥 Commits

Reviewing files that changed from the base of the PR and between f1de57f and 5810059.

📒 Files selected for processing (1)
  • test/ssh_config_test.dart
✅ Files skipped from review due to trivial changes (1)
  • test/ssh_config_test.dart

📝 Walkthrough

Walkthrough

The PR trims proxyCommand, treating empty/whitespace-only values as null, and when both ProxyJump and ProxyCommand are present it prefers ProxyCommand. Host validation was changed from throwing (validateOrThrow) to non-throwing validate() with invalid hosts skipped and a warning logged. Inline comment stripping was refactored into _stripInlineComment with a @visibleForTesting wrapper stripInlineCommentForTest that preserves # inside single/double quotes and trims trailing comments. A SpiValidationException type was added and UI save/import flows now surface localized messages for validation errors.

Possibly related PRs

Suggested reviewers

  • lollipopkit
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: harden ProxyCommand SSH config parsing and validation' directly addresses the main changes, which include improved ProxyCommand parsing, validation hardening, and exception handling across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
lib/core/utils/ssh_config.dart (1)

185-217: Add focused tests for _stripInlineComment edge cases.

Given Line 185–217 now handles escaping and quote state, please add parser tests for: quoted #, escaped \#, and whitespace-prefixed inline comments.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/core/utils/ssh_config.dart` around lines 185 - 217, Add focused unit
tests for the _stripInlineComment function to cover the newly-handled edge
cases: (1) a '#' character inside single and double quotes which should be
preserved (e.g., "'#'" and '"#"' return the full string), (2) an escaped hash
like '\#' which should not start a comment and should be preserved, and (3) a
true inline comment that is whitespace-prefixed (e.g., "value  # comment") which
should return only the part before the comment. Create tests that assert exact
expected outputs for each case and include examples combining escapes and quotes
to ensure the parser's escaped/quote state handling in _stripInlineComment is
validated.
lib/view/page/server/edit/actions.dart (1)

7-12: Reuse _validationErrorMessage in _onSave to keep one source of truth.

Line 7–12 introduces a good mapper, but _onSave still hardcodes the same message path. Centralizing avoids drift when new SpiValidationError values are added.

Refactor proposal
-    final validationError = spi.validate();
-    if (validationError ==
-        SpiValidationError.jumpServerAndProxyCommandConflict) {
-      context.showSnackBar(
-        l10n.jumpServerAndProxyCommandCannotBeUsedTogether,
-      );
-      return;
-    }
+    final validationError = spi.validate();
+    if (validationError != null) {
+      context.showSnackBar(_validationErrorMessage(validationError));
+      return;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/view/page/server/edit/actions.dart` around lines 7 - 12, The _onSave
handler duplicates a validation message instead of using the central mapper;
update _onSave to call _validationErrorMessage(error) (where error is the
SpiValidationError returned during save) and use its returned string for the
UI/logging; also make _validationErrorMessage(SpiValidationError) exhaustive or
add a default/fallback return so it never returns null (e.g., a generic
l10n.validationFailed) to avoid runtime nulls when new SpiValidationError values
are added.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/core/utils/ssh_config.dart`:
- Around line 185-217: Add focused unit tests for the _stripInlineComment
function to cover the newly-handled edge cases: (1) a '#' character inside
single and double quotes which should be preserved (e.g., "'#'" and '"#"' return
the full string), (2) an escaped hash like '\#' which should not start a comment
and should be preserved, and (3) a true inline comment that is
whitespace-prefixed (e.g., "value  # comment") which should return only the part
before the comment. Create tests that assert exact expected outputs for each
case and include examples combining escapes and quotes to ensure the parser's
escaped/quote state handling in _stripInlineComment is validated.

In `@lib/view/page/server/edit/actions.dart`:
- Around line 7-12: The _onSave handler duplicates a validation message instead
of using the central mapper; update _onSave to call
_validationErrorMessage(error) (where error is the SpiValidationError returned
during save) and use its returned string for the UI/logging; also make
_validationErrorMessage(SpiValidationError) exhaustive or add a default/fallback
return so it never returns null (e.g., a generic l10n.validationFailed) to avoid
runtime nulls when new SpiValidationError values are added.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3ea0ae4f-36c7-4d56-af1c-0d7174e6b043

📥 Commits

Reviewing files that changed from the base of the PR and between f9e27db and b888157.

⛔ Files ignored due to path filters (1)
  • lib/generated/l10n/l10n_zh.dart is excluded by !**/generated/**
📒 Files selected for processing (3)
  • lib/core/utils/ssh_config.dart
  • lib/data/model/server/server_private_info.dart
  • lib/view/page/server/edit/actions.dart

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 10, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/ssh_config_test.dart (1)

355-389: Good test coverage for the inline comment stripping logic.

The tests cover the key scenarios well. Consider adding a test for the edge case where # appears without preceding whitespace (e.g., 'foo#bar' should remain unchanged since # is not preceded by whitespace):

💡 Optional: additional edge case test
      test('preserves hash not preceded by whitespace', () {
        expect(
          SSHConfig.stripInlineCommentForTest('foo#bar'),
          'foo#bar',
        );
      });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ssh_config_test.dart` around lines 355 - 389, Add a unit test to cover
the edge case where a hash appears without preceding whitespace so it isn't
treated as an inline comment: add a new test in the _stripInlineComment group
that calls SSHConfig.stripInlineCommentForTest('foo#bar') and expects 'foo#bar'
to be returned (reference: SSHConfig.stripInlineCommentForTest and the
_stripInlineComment test group).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/ssh_config_test.dart`:
- Around line 355-389: Add a unit test to cover the edge case where a hash
appears without preceding whitespace so it isn't treated as an inline comment:
add a new test in the _stripInlineComment group that calls
SSHConfig.stripInlineCommentForTest('foo#bar') and expects 'foo#bar' to be
returned (reference: SSHConfig.stripInlineCommentForTest and the
_stripInlineComment test group).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3cabd119-713d-48f2-a018-e294ce364df8

📥 Commits

Reviewing files that changed from the base of the PR and between b888157 and f1de57f.

📒 Files selected for processing (3)
  • lib/core/utils/ssh_config.dart
  • lib/view/page/server/edit/actions.dart
  • test/ssh_config_test.dart
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/view/page/server/edit/actions.dart

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 10, 2026
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@GT-610 GT-610 merged commit 498291b into lollipopkit:main Apr 10, 2026
2 checks passed
@GT-610 GT-610 deleted the proxycommand-continue-fix branch April 10, 2026 03:32
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