Commit 0446d8d
fix(presets): raise PresetValidationError, not raw ValueError, on malformed catalog URL
`PresetCatalog._validate_catalog_url` called `urlparse(url).hostname` without
guarding it. For a malformed authority such as an unterminated IPv6 bracket
(`https://[::1`), `urlparse(...).hostname` raises `ValueError: Invalid IPv6 URL`,
which escapes the method. Its docstring promises `PresetValidationError`, and its
callers (`preset catalog add`, `preset catalog list` reading the
`SPECKIT_PRESET_CATALOG_URL` env var / `.specify/preset-catalogs.yml`) only catch
`PresetValidationError` -- so a malformed URL crashes the CLI with a traceback
instead of a clean error message.
The shared `CatalogStackBase` (#3435), `workflows` (#3484), `bundler` (#3433) and
`IntegrationCatalog` copies already wrap this in `try/except ValueError`; the
preset validator was the remaining un-updated twin. Mirror the shared
implementation: wrap `urlparse` + `.hostname`, re-raise as
`PresetValidationError("Catalog URL is malformed: ...")`, and read the local
`hostname` in the host check.
Add a regression test mirroring `IntegrationCatalog`'s
`test_malformed_url_rejected_cleanly`; it is red before the fix (raw `ValueError`)
and green after.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 7bdf6c5 commit 0446d8d
2 files changed
Lines changed: 19 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2074 | 2074 | | |
2075 | 2075 | | |
2076 | 2076 | | |
2077 | | - | |
2078 | | - | |
| 2077 | + | |
| 2078 | + | |
| 2079 | + | |
| 2080 | + | |
| 2081 | + | |
| 2082 | + | |
2079 | 2083 | | |
2080 | 2084 | | |
2081 | 2085 | | |
| |||
2086 | 2090 | | |
2087 | 2091 | | |
2088 | 2092 | | |
2089 | | - | |
| 2093 | + | |
2090 | 2094 | | |
2091 | 2095 | | |
2092 | 2096 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1634 | 1634 | | |
1635 | 1635 | | |
1636 | 1636 | | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
| 1641 | + | |
| 1642 | + | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
| 1646 | + | |
| 1647 | + | |
| 1648 | + | |
1637 | 1649 | | |
1638 | 1650 | | |
1639 | 1651 | | |
| |||
0 commit comments