Skip to content

feat(pam tunnel): foreground/background/run + cross-process registry (rebase onto upstream master)#15

Open
msawczynk wants to merge 4 commits into
masterfrom
cursor/pam-tunnel-rebase-upstream-c427
Open

feat(pam tunnel): foreground/background/run + cross-process registry (rebase onto upstream master)#15
msawczynk wants to merge 4 commits into
masterfrom
cursor/pam-tunnel-rebase-upstream-c427

Conversation

@msawczynk

Copy link
Copy Markdown
Owner

Reapplies the PAM non-interactive tunnel work in four commits, rebased onto current Keeper-Security/Commander master (fetched as upstream/master).

Contents

  • pam tunnel start: --foreground / --background / --run / --pid-file / --timeout, file-based keeper-tunnel-sessions registry, list/stop across processes
  • keepercommander/commands/tunnel_registry.py
  • unit-tests/test_tunnel_registry.py (15 unit tests; pytest unit-tests/test_tunnel_registry.py passes)
  • tunnel_helpers: parse_keeper_webrtc_version_from_sdp helpers for import chain compatibility

Next step for upstream

  • Open a second PR from msawczynk/Commander cursor/pam-tunnel-rebase-upstream-c427Keeper-Security/Commander:master (or release if that is the integration branch).

Related context: original Keeper-Security#1848.

Open in Web Open in Cursor 

msawczynk and others added 4 commits April 24, 2026 22:35
…urn, port safety

- Add Windows hard-termination warning to --background and --run banners (was only on --foreground)
- Use clean_stale=False in --background polling loop to avoid filesystem churn every 0.5s
- Guard port comparison in register_tunnel against non-int-coercible values
- Document normalize_bind_host limitation (0.0.0.0 vs 127.0.0.1 caught at OS level)
- Note thread-safety characteristic of _registry_dir_initialized flag

Made-with: Cursor
… in tunnel_helpers

The original feat commit was authored against release 17.2.10, which did
not yet contain parse_keeper_webrtc_version_from_sdp / set_remote_description_and_parse_version.
During the feat-commit refactor those helpers were removed. Upstream has
since added both (commit efdf580 and its precursor) and
pam_launch/terminal_connection.py imports them. After rebasing this PR
onto current upstream/release, the removal became a regression:

    ImportError: cannot import name 'parse_keeper_webrtc_version_from_sdp'
    from 'keepercommander.commands.tunnel.port_forward.tunnel_helpers'

Restore both helpers verbatim from upstream/release so the import chain
(pam_launch -> terminal_connection -> tunnel_helpers) resolves again.
Unit tests (15) + full import chain verified locally.

Made-with: Cursor

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 636faee. Configure here.

# return

automators = json.loads(self.dump_automators(params,fmt='json'))
conflict_automators = [automator['name'] for automator in automators if automator['node_id']==1067368092533492 and automator['enabled']]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hardcoded node_id instead of using resolved variable

High Severity

The conflict check on line 292 compares automator['node_id'] against the hardcoded value 1067368092533492 instead of the dynamically resolved matched_node_id. This means the "existing automators in this node" warning only fires for one specific node (likely a developer's test environment) and silently skips the check for every other node. The filter expression needs to use matched_node_id instead of the literal integer.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 636faee. Configure here.

global _gateway_cache_result, _gateway_cache_time
now = time.time()
if _gateway_cache_result is not None and (now - _gateway_cache_time) < _GATEWAY_CACHE_TTL:
return _gateway_cache_result

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Gateway cache reads globals without holding lock

Low Severity

get_all_gateways reads both _gateway_cache_result and _gateway_cache_time outside the lock on lines 38–40. A concurrent call to invalidate_gateway_cache could set _gateway_cache_result = None after the is not None check passes but before the return, causing the function to return None instead of a valid controller list. The pre-lock check is an optimization but introduces a TOCTOU window with invalidate_gateway_cache.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 636faee. Configure here.

cli_scale: Optional[int] = None,
connect_banner_title: Optional[str] = None,
pre_connect_spinner: Optional[PamLaunchSpinner] = None,
preserve_crlf: bool = True,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Parameter preserve_crlf accepted but never used

Low Severity

The preserve_crlf parameter is declared in _start_cli_session and passed from execute(), but it is never read or referenced anywhere in the method body. The CRLF normalization flag actually flows through kwargslaunch_terminal_connection_build_guacamole_connection_settingsPythonHandler. This dead parameter suggests either missing logic in _start_cli_session or an unnecessary indirection that could confuse future maintainers.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 636faee. Configure here.

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