Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

VEX product purl detected from pyproject.toml keeps the raw project name (pkg:pypi/My_Service) instead of the normalized pypi name

Closed Beginner friendly
#1,547 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

A pull request for this has already been merged.

  • #1577 by @mikolalysenko — merged

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
80/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python, rust
Domain
security

Research direction

The bug is in parse_pyproject in crates/socket-patch-core/src/vex/product.rs (around lines 157-167), which builds the pypi purl from the raw project name. Compare it with the npm and composer branches in the same file, which already lowercase names, and check the PEP 503 helpers the issue mentions. Done means My_Service yields pkg:pypi/[email protected] and Demo_Pkg.Core yields pkg:pypi/[email protected], with a unit test covering both.

Written by the indexing model from the issue text.

Description

agent:triaged bug bughunt pm:poetry priority:p1

[agent] Found by the scheduled Poetry bug-hunt routine (ledger #311).

Summary

When vex (or scan --vex / apply --vex) auto-detects the top-level product from pyproject.toml, it copies the project name verbatim into the purl. A Poetry project named My_Service gets the product pkg:pypi/[email protected], and Demo_Pkg.Core gets pkg:pypi/[email protected]. The purl spec's pypi type says the name must be lowercased with _ replaced by - (PyPI compares names in PEP 503 form, which also maps . to -). So the expected products are pkg:pypi/[email protected] and pkg:pypi/[email protected] (demo-pkg-core in full PEP 503 form).

The npm and composer branches of the same detector already lowercase their names (product.rs, e.g. parse_composer_json), and the rest of the codebase compares PyPI names in PEP 503 form (crawlers/fuzzy_match.rs, crawlers/hatch_env.rs). Only the pyproject branch skips it.

Impact

An OpenVEX consumer matches products[].@id against the product identifier in the SBOM or scan it is applied to. SBOM generators emit the normalized pypi purl, so a VEX document saying pkg:pypi/My_Service@… won't match the project by exact purl, and its not_affected statements are silently ignored. That affects every Python project whose name has uppercase letters or _, which is common: Poetry, PDM and hatch all accept and preserve such names. It isn't Poetry-specific; any pyproject-based product goes through parse_pyproject. --vex-product / --product work around it.

Repro (Linux, main fc1b4f9)

Uses a local mock of the patch API serving one patched six-1.16.0 wheel. The same result comes from any pypi patch.

# Poetry 2.5.1, PEP 621 layout, agent mode + standalone vex
mkdir proj && cd proj
printf '[project]\nname = "My_Service"\nversion = "1.2.0"\nrequires-python = ">=3.9"\ndependencies = ["six==1.16.0"]\n\n[tool.poetry]\npackage-mode = false\n' > pyproject.toml
POETRY_VIRTUALENVS_IN_PROJECT=true poetry lock && poetry install
socket-patch scan --mode agent --json --yes --api-url $MOCK --api-token x --org test-org
socket-patch vex -O v.json --json --api-url $MOCK --api-token x --org test-org
jq -r '.statements[].products[]."@id"' v.json
# → pkg:pypi/[email protected]      (expected pkg:pypi/[email protected])

# Poetry 1.8.5, legacy [tool.poetry] layout, hosted + same-run VEX
#   [tool.poetry] name = "My_Service", version = "0.1.0", six = "1.16.0"
socket-patch scan --mode hosted --vex out.vex.json --json --yes …
# → pkg:pypi/[email protected]

# Poetry 2.5.1, [tool.poetry] name = "Demo_Pkg.Core"
# → pkg:pypi/[email protected]

For reference, packaging.utils.canonicalize_name("My_Service") is my-service.

Expected vs actual

  • Expected: CLI_CONTRACT.md / product.rs's module doc say pyproject.toml maps to pkg:pypi/<name>@<version>, and a pypi purl's name is the normalized one (purl spec, pypi type: lowercase, _ → -), as the component purls in the same document already are (pkg:pypi/[email protected]).
  • Actual: the name is emitted byte for byte as written in [project].name / [tool.poetry].name.

OS × version

OS Poetry Layout Path Result
Linux 1.8.5 [tool.poetry] scan --mode hosted --vex reproduces
Linux 2.5.1 [project] agent scan + vex reproduces
Linux 2.5.1 [tool.poetry] scan --mode hosted --vex reproduces
macOS / Windows any any — not run (the code path is OS-independent string handling)

Suspect code

crates/socket-patch-core/src/vex/product.rs:157-167 (parse_pyproject builds format!("pkg:pypi/{name}@{version}") from pyproject_name_version without normalizing). The PEP 503 helper consolidated under #883 could be reused here.

Dominant language
Rust
Stars
8
Forks
1
Avg merge
16h 18m
Merged PRs (30d)
587

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SocketDev/socket-patch

All issues in SocketDev/socket-patch

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.