fix(pypi): encode extras names fully, and mark the remaining raw sites safe - #1356
Merged
Conversation
…s safe
The extras path (`requests[socks]`) assembled its PURL by hand so the bracket
escapes could be lowercase, matching what ScanCode emits. That left every *other*
character raw, so a lockfile name carrying both a bracket and a reserved
character kept the latter unencoded. Encode through the crate and lowercase only
the two bracket escapes, which keeps the emitted spelling identical while closing
the gap.
The `format!("pkg:` sites that remain are all safe, and now say why — the whole
reason this class of bug survived is that every such site looked alike under
grep:
- The pypi builders restrict the name to the PEP 508 charset before formatting,
which needs no percent-encoding, and encode the version separately.
- The CocoaPods ones are internal map keys that are never emitted; the emitted
PURL comes from `create_cocoapods_purl`, which encodes through the crate.
- Go's namespace splice is already documented: it preserves path-part case, which
`normalize_purl` then lowercases host-only per purl-spec#308.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Maxim Stykow <maxim.stykow@gmail.com>
Greptile SummaryThis PR corrects PyPI PURL construction for package names containing extras while documenting why remaining manual PURL construction sites are safe.
Confidence Score: 5/5The PR appears safe to merge, with no concrete correctness, security, or repository-rule violations identified. The changed Poetry and uv paths now encode complete PURL components through the shared helper while deliberately preserving the established bracket-escape spelling, and the remaining changes only document existing safety invariants.
|
| Filename | Overview |
|---|---|
| src/parsers/poetry_lock.rs | Replaces partial manual encoding of extras-bearing PyPI names with shared PURL construction while preserving lowercase bracket escapes. |
| src/parsers/uv_lock.rs | Applies the same complete encoding path to uv lockfile dependency names containing extras. |
| src/parsers/podfile_lock.rs | Documents that the unencoded CocoaPods base PURL string is an internal map key rather than emitted output. |
| src/parsers/python/utils.rs | Documents the validation and version-encoding guarantees that make local PyPI PURL assembly safe. |
| src/parsers/requirements_txt.rs | Documents why validated distribution names and separately encoded versions can be assembled safely. |
Reviews (1): Last reviewed commit: "fix(pypi): encode extras names fully, an..." | Re-trigger Greptile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
requests[socks]) assembled its PURL by hand so the bracket escapes could be lowercase, matching what ScanCode emits. That left every other character raw, so a lockfile name carrying both a bracket and a reserved character kept the latter unencoded. It now encodes through the crate and lowercases only the two bracket escapes, so the emitted spelling is unchanged and the gap is closed.format!("pkg:…")that remains is safe, and now says why — the reason this class of bug survived is that every such site looked alike under grep.Scope and exclusions
The remaining sites, each now carrying its justification:
1.0+cu118and4.%2Aboth parse and decode to the same components either way.make_base_purl/make_base_purl_from_partsare internal map keys, never emitted. Emitted PURLs come fromcreate_cocoapods_purl, which encodes through the crate.normalize_purlthen lowercases host-only per purl-spec#308.src/output/cyclonedx.rsis insidemod tests.How to verify
Every hit should now be adjacent to a comment saying why it is not an emission site or why the components need no encoding. Behaviourally, a
uv.lock/poetry.lockentry namedfoo bar[extra]previously emitted an unencoded space; it now encodes, whilerequests[socks]is byte-identical to before.Intentional differences from Python
%5b/%5drather than the crate's%5B/%5D) are kept deliberately for ScanCode parity. Both decode identically.Expected-output fixture changes