Skip to content

fix(extensions,presets): surface clean error on malformed download URL#3577

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/download-url-malformed-valueerror
Open

fix(extensions,presets): surface clean error on malformed download URL#3577
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/download-url-malformed-valueerror

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

ExtensionCatalog.download_extension and PresetCatalog.download_pack read a download_url from catalog payload data and pass it through urlparse(...).hostname during their HTTPS validation. A malformed authority — e.g. an unterminated IPv6 bracket like https://[::1, or https://[not-an-ip]/x — makes urlparse/.hostname raise a raw ValueError.

That ValueError escapes the command handlers, which only catch ExtensionError / PresetError, so instead of a clean CLI message the user gets an uncaught traceback.

This wraps the parse in a try/except ValueError and re-raises as the module's domain error (ExtensionError / PresetError) with a clear "download URL is malformed" message.

Bug class

Same shape as the already-fixed unguarded-urlparse leaks in:

This closes the two remaining sibling code paths (extensions + presets) that had the same latent crash.

Changes

  • src/specify_cli/extensions/__init__.py — guard the download_url parse in download_extension.
  • src/specify_cli/presets/__init__.py — guard the download_url parse in download_pack.
  • tests/test_extensions.py — regression test asserting a malformed URL raises ExtensionError (not ValueError).
  • tests/test_presets.py — matching regression test for download_pack.

Testing

  • New tests fail on the pre-fix source (raw ValueError) and pass with the guard ("test-the-test" verified).
  • Full tests/test_extensions.py and tests/test_presets.py pass (717 passed, 5 skipped).

🤖 Generated with Claude Code

`ExtensionCatalog.download_extension` and `PresetCatalog.download_pack` read
`download_url` from catalog payload data and pass it to `urlparse(...).hostname`
during the HTTPS validation. A malformed authority (e.g. an unterminated IPv6
bracket like `https://[::1`) makes urlparse/hostname raise a raw `ValueError`,
which escapes past the command handlers — they only catch `ExtensionError` /
`PresetError` — and surfaces as an uncaught traceback.

Guard the parse in a try/except and re-raise as the domain error so the CLI
reports a clean "download URL is malformed" message. Mirrors the same fix in
catalogs (github#3435) and workflows/catalog.py (github#3484).

Adds regression coverage for both catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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

Converts malformed extension and preset download URLs into domain-specific errors.

Changes:

  • Guards URL parsing and hostname access.
  • Adds regression coverage for malformed IPv6 authorities.
Show a summary per file
File Description
src/specify_cli/extensions/__init__.py Raises ExtensionError for malformed URLs.
src/specify_cli/presets/__init__.py Raises PresetError for malformed URLs.
tests/test_extensions.py Tests malformed extension URLs.
tests/test_presets.py Tests malformed preset URLs.

Review details

Tip

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

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

hostname = parsed.hostname
except ValueError:
raise PresetError(
f"Preset download URL is malformed: {download_url}"

@mnriem mnriem left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please address Copilot feedback

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.

3 participants