Skip to content

fix(bundler): validate catalog URLs in catalog add (HTTPS-only, require host)#3367

Open
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/3366-catalog-add-url-validation
Open

fix(bundler): validate catalog URLs in catalog add (HTTPS-only, require host)#3367
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/3366-catalog-add-url-validation

Conversation

@marcelsafin

Copy link
Copy Markdown

Description

Fixes #3366

specify bundle catalog add persisted remote catalog URLs into catalogs.yaml without any HTTPS or host validation, and a malformed IPv6 URL (https://[::1/c.json) escaped the command's except BundlerError handler as a raw ValueError traceback.

Root cause: add_source in bundler/commands_impl/catalog_config.py is the third copy of the catalog-URL validation contract — specify_cli.catalogs._validate_catalog_url (#3210) and bundler/services/adapters._validate_remote_url (#3333) both enforce HTTPS-only (HTTP for localhost) with a hostname check, but the CLI entry point that actually writes the config had neither.

Before: http://evil.example.com/catalog.json, https://:8080, https://user@✓ Added catalog ... (fails later at fetch time); https://[::1/c.json → traceback.
After: all four rejected with a clear BundlerError at add time; file://, builtin://, local paths, and http://localhost unaffected.

Also guarded the urlparse call in _is_local_path so remove_source's canonicalization fallback doesn't crash on the same malformed input.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest — 3832 passed, 87 skipped
  • Tested with a sample project (if applicable)

5 new unit tests in tests/unit/test_bundler_catalog_config.py: plain-HTTP rejection, localhost-HTTP allowance, host-less rejection (https://:8080, https://user@), and BundlerError (not ValueError) on malformed IPv6 for both add_source and remove_source.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Bug found, patch and tests written with GitHub Copilot CLI; all changes reviewed, and the reproduction + full test suite run and verified locally by me.

…uire host)

add_source persisted remote catalog URLs without the HTTPS/host checks
that specify_cli.catalogs (github#3210) and the bundler adapters (github#3333)
enforce, and an unclosed IPv6 bracket escaped as a raw ValueError.
Mirror the catalogs.py validation for http(s) schemes and wrap urlparse
so malformed input raises BundlerError.

Fixes github#3366

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes specify bundle catalog add so it validates remote catalog URLs before persisting them to the project’s bundler catalog config, preventing insecure/invalid URLs from being stored and ensuring malformed inputs raise BundlerError instead of leaking ValueError tracebacks.

Changes:

  • Add HTTPS-only enforcement for non-localhost http(s):// catalog URLs and require a real host (via parsed.hostname) at add time.
  • Guard URL parsing in _is_local_path/add_source so malformed URLs (e.g., invalid IPv6 brackets) don’t crash the command.
  • Add unit tests covering plain-HTTP rejection, localhost-HTTP allowance, host-less rejection, and malformed IPv6 error wrapping for both add/remove flows.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/specify_cli/bundler/commands_impl/catalog_config.py Adds URL parsing guards and enforces HTTPS/host validation for remote catalog URLs during add_source (plus safer handling in _is_local_path).
tests/unit/test_bundler_catalog_config.py Adds regression tests for the new validation behavior and malformed IPv6 handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +159 to +163
# Mirror specify_cli.catalogs / bundler adapters URL validation
# (#3209/#3210): HTTPS only (HTTP just for localhost), and check
# hostname, not netloc — netloc is truthy for host-less URLs like
# "https://:8080" or "https://user@". Validating here keeps junk out
# of catalogs.yaml instead of failing later at fetch time.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch — the module writes bundle-catalogs.yml (CONFIG_FILENAME), not catalogs.yaml, and the adapters' host check is only aligned once #3333 lands. Comment now references specify_cli.catalogs._validate_catalog_url and the correct filename. Fixed in cd6ddc7.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Low

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.

Bug: bundle catalog add persists un-validated catalog URLs (plain HTTP, host-less) and crashes on malformed IPv6

3 participants