@@ -91,7 +91,8 @@ class Distribution(BaseModel):
91
91
@field_validator ("name" )
92
92
@classmethod
93
93
def _validate_name (cls , v : str ) -> str :
94
- return _ultranormalize_dist_filename (v )
94
+ _check_dist_filename (v )
95
+ return v
95
96
96
97
@classmethod
97
98
def from_file (cls , dist : Path ) -> Distribution :
@@ -283,8 +284,15 @@ def verify(
283
284
raise VerificationError ("invalid subject: missing name" )
284
285
285
286
try :
286
- # We always ultranormalize when signing, but other signers may not.
287
- subject_name = _ultranormalize_dist_filename (subject .name )
287
+ # We don't allow signing of malformed distribution names.
288
+ # Previous versions of this package went further than this
289
+ # and "ultranormalized" the name, but this was superfluous
290
+ # and caused confusion for users who expected the subject to
291
+ # be an exact match for their distribution filename.
292
+ # See: https://github.com/pypi/warehouse/issues/18128
293
+ # See: https://github.com/trailofbits/pypi-attestations/issues/123
294
+ _check_dist_filename (subject .name )
295
+ subject_name = subject .name
288
296
except ValueError as e :
289
297
raise VerificationError (f"invalid subject: { str (e )} " )
290
298
@@ -384,57 +392,24 @@ def _der_decode_utf8string(der: bytes) -> str:
384
392
return der_decode (der , UTF8String )[0 ].decode () # type: ignore[no-any-return]
385
393
386
394
387
- def _ultranormalize_dist_filename (dist : str ) -> str :
388
- """Return an "ultranormalized" form of the given distribution filename.
395
+ def _check_dist_filename (dist : str ) -> None :
396
+ """Validate a distribution filename for well-formedness .
389
397
390
- This form is equivalent to the normalized form for sdist and wheel
391
- filenames, with the additional stipulation that compressed tag sets,
392
- if present, are also sorted alphanumerically.
398
+ This does **not** fully normalize the filename. For example,
399
+ a user can include a non-normalized version string or package name
400
+ (or compressed tag set in the case of wheels), and this function
401
+ will **not** reject so long as it parses correctly.
393
402
394
403
Raises `ValueError` on any invalid distribution filename.
395
404
"""
396
405
# NOTE: .whl and .tar.gz are assumed lowercase, since `packaging`
397
406
# already rejects non-lowercase variants.
398
407
if dist .endswith (".whl" ):
399
408
# `parse_wheel_filename` raises a supertype of ValueError on failure.
400
- name , ver , build , tags = parse_wheel_filename (dist )
401
-
402
- # The name has been normalized to replace runs of `[.-_]+` with `-`,
403
- # which then needs to be replaced with `_` for the wheel.
404
- name = name .replace ("-" , "_" )
405
-
406
- # `parse_wheel_filename` normalizes the name and version for us,
407
- # so all we need to do is re-compress the tag set in a canonical
408
- # order.
409
- # NOTE(ww): This is written in a not very efficient manner, since
410
- # I wasn't feeling smart.
411
- impls , abis , platforms = set (), set (), set ()
412
- for tag in tags :
413
- impls .add (tag .interpreter )
414
- abis .add (tag .abi )
415
- platforms .add (tag .platform )
416
-
417
- impl_tag = "." .join (sorted (impls ))
418
- abi_tag = "." .join (sorted (abis ))
419
- platform_tag = "." .join (sorted (platforms ))
420
-
421
- if build :
422
- parts = "-" .join (
423
- [name , str (ver ), f"{ build [0 ]} { build [1 ]} " , impl_tag , abi_tag , platform_tag ]
424
- )
425
- else :
426
- parts = "-" .join ([name , str (ver ), impl_tag , abi_tag , platform_tag ])
427
-
428
- return f"{ parts } .whl"
409
+ parse_wheel_filename (dist )
429
410
elif dist .endswith ((".tar.gz" , ".zip" )):
430
411
# `parse_sdist_filename` raises a supertype of ValueError on failure.
431
- name , ver = parse_sdist_filename (dist )
432
- name = name .replace ("-" , "_" )
433
-
434
- if dist .endswith (".tar.gz" ):
435
- return f"{ name } -{ ver } .tar.gz"
436
- else :
437
- return f"{ name } -{ ver } .zip"
412
+ parse_sdist_filename (dist )
438
413
else :
439
414
raise ValueError (f"unknown distribution format: { dist } " )
440
415
0 commit comments