Skip to content

[BUG] SCP shorthand with numeric port silently misparsed as repo path #784

@edenfunf

Description

@edenfunf

Problem

When a user specifies an SCP-shorthand SSH dependency with a port number — e.g. from a Bitbucket Datacenter server — the parser silently treats the port as part of the repo path instead of raising an actionable error:

dependencies:
  apm:
    - git@bitbucket.example.com:7999/project/repo.git

Parsed result:

Field Value
host bitbucket.example.com
port None
repo_url 7999/project/repo

The user intended port 7999 with repo project/repo, but APM accepted 7999/project/repo as a valid three-segment repo path. The subsequent git clone fails with a 404 from the remote — not an APM error message pointing at the SCP/port mismatch.

To Reproduce

# apm.yml
dependencies:
  apm:
    - git@bitbucket.example.com:7999/project/repo.git
  1. Run apm install --verbose
  2. Clone fails with repository not found from git
  3. No APM-level warning about the SCP/port ambiguity

Expected behavior

APM should detect the leading numeric segment and raise an actionable error:

Error: 'git@bitbucket.example.com:7999/project/repo.git' — '7999' looks like
a port number, but SCP shorthand (git@host:path) cannot carry a port.
Use: ssh://git@bitbucket.example.com:7999/project/repo.git

Root cause

_parse_ssh_url (reference.py:648) uses the regex ^git@([^:]+):(.+)$ which captures everything after : as the repo path. Phase 3 validation ([a-zA-Z0-9._-]+ per segment) accepts purely numeric segments like 7999. No heuristic exists to detect the ambiguity.

Suggested fix

After extracting repo_url in _parse_ssh_url (line 671), check if the first path segment is a valid port number:

segments = repo_url.split("/")
first = segments[0]
if first.isdigit():
    port_candidate = int(first)
    if 1 <= port_candidate <= 65535:
        remaining = "/".join(segments[1:])
        raise ValueError(
            f"It looks like '{first}' in 'git@{host}:{repo_url}' is a port number, "
            f"but SCP shorthand cannot carry a port. "
            f"Use: ssh://git@{host}:{first}/{remaining}.git"
        )

False positive analysis: purely numeric org/owner names are not allowed on GitHub and extremely rare on other hosts (GitLab namespaces require at least one letter). If a user does have one, the error message directs them to the ssh:// form which unambiguously separates port from path.

Tests to add

  • git@host:7999/project/repo.git → raises ValueError with suggestion
  • git@host:22/project/repo.git → same (default port, still a port intention)
  • git@host:acme/repo.git → no error (non-numeric first segment, existing behavior)
  • git@host:v2/repo.git → no error (starts with letter)

Context

Follow-up from PR #665 (port preservation). Identified in the review panel's devx-ux-expert finding.

Refs: #661, #665

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions