Skip to content

feat(pep621): surface uv.lock transitive deps for osvVulnerabilityAlerts#44262

Open
khvn26 wants to merge 4 commits into
renovatebot:mainfrom
khvn26:feat/uv-transitive-osv-remediation
Open

feat(pep621): surface uv.lock transitive deps for osvVulnerabilityAlerts#44262
khvn26 wants to merge 4 commits into
renovatebot:mainfrom
khvn26:feat/uv-transitive-osv-remediation

Conversation

@khvn26

@khvn26 khvn26 commented Jun 26, 2026

Copy link
Copy Markdown

Changes

In this PR, we let osvVulnerabilityAlerts remediate vulnerabilities in transitive (lockfile-only) dependencies for the uv manager.

Today the pep621/uv manager only attaches lockedVersion to dependencies declared in pyproject.toml. Packages that exist solely in uv.lock are parsed and then discarded, so osvVulnerabilityAlerts can never see a CVE in an indirect dependency. lockFileMaintenance is the only current workaround and it isn't security-scoped.

This surfaces those transitive packages so the existing vulnerability machinery can act on them.

  • UvProcessor.extractLockedVersions now emits each registry-sourced package that isn't already a declared dependency as a PackageDependency with depType: 'uv.lock', its lockedVersion, and enabled: false. Because they're disabled, they produce no routine updates.
  • The UvLockfile schema now captures each package's source.registry. The workspace root and any packages not resolved from an index have no registry and are skipped. Non-default indexes are carried through as registryUrls.
  • The package rule generated by osvVulnerabilityAlerts now sets enabled: true. A disabled dependency is therefore re-enabled only when a fixed version exists for a matched advisory. That rule is applied at the pre-lookup stage, before the enabled === false gate, so remediation flows into the existing uv lock --upgrade-package <name> call.

The re-enable on the generated rule is the one cross-ecosystem behavior change: a vulnerable dependency that a user has otherwise disabled will now get a remediation PR when a fix is available. This is consistent with how vulnerability alerts already override schedule and minimumReleaseAge.
The same mechanism would generalize to other lockfile managers (poetry, PEP 751, cargo); this PR keeps it to uv as a first implementation.

Some quirks I've noticed and would like to point out/discuss:

  • Transitive deps from non-default indexes carry the index URL from uv.lock as registryUrls. Credentials from those come from hostRules the same way it's done for non-transitive deps.
  • In a workspace with multiple pyproject.toml files sharing one uv.lock, we can get multiple remediations for the same transitive dep. Not sure if Renovate dedupes those further down the line, or we need to dedup earlier.

Context

Please select one of the following:

  • This closes an existing Issue, Closes: #
  • This doesn't close an Issue, but I accept the risk that this PR may be closed if maintainers disagree with its opening or implementation

Related discussions: #36793, #22049. I opted to open a PR with a working, tested implementation rather than only a proposal, but I'm very happy to convert this to a discussion-first conversation if you'd rather agree the approach before reviewing code.

AI assistance disclosure

Did you use AI tools to create any part of this pull request?

  • Yes — substantive assistance (AI-generated non-trivial portions of code, tests, or documentation).

The code and tests were written by Claude Code (model: Claude Opus 4.8), with me directing the work, reviewing each change, and running the test suite.

Documentation (please check one with an [x])

  • I have updated the documentation, or
  • No documentation update is required

(The new uv.lock depType carries a description via dep-types.ts, which feeds the generated manager docs.)

How I've tested my work (please select one)

I have verified these changes via:

  • Both unit tests + ran on a real repository

Unit tests: added an extract test covering transitive emission, and asserted the generated vulnerability rule now sets enabled: true.

Reproduction repo and the resulting PR:

Emit registry-sourced lockfile-only packages as disabled deps so OSV can match them, and re-enable remediation only when a fixed version exists for a matched advisory.
@github-actions github-actions Bot requested a review from viceice June 26, 2026 17:00

@RahulGautamSingh RahulGautamSingh 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.

Thanks for the PR! It has been a widely asked feature which we have implemented and then reverted for npm ie. transitiveRemediation so please give the team sometime to build a consensus on this.

Also, due to summer holidays it could take some time for the reviews and discussions.

I'll in post my review of the implementation soon.

Comment thread lib/modules/manager/pep621/schema.ts Outdated
Comment on lines +224 to +226
// The index a package was resolved from, if any. Absent for the workspace
// root and for virtual/editable/path/git packages, which cannot be
// remediated by `uv lock --upgrade-package`.

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.

use jsdoc comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Comment on lines +1130 to +1131
// remediation must override a disabled dependency, e.g. a transitive
// dep surfaced from a lockfile

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.

jsdoc comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Comment on lines +603 to +605
// Remediate even when updates are otherwise disabled for the dependency,
// e.g. transitive deps surfaced from a lockfile. Consistent with how
// vulnerability alerts already override schedule and minimumReleaseAge.

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.

jsdoc comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

'https://pypi.org/simple/',
]);

function isDefaultPypiRegistry(registryUrl: string): boolean {

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.

only used once, inline this

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

// Remediate even when updates are otherwise disabled for the dependency,
// e.g. transitive deps surfaced from a lockfile. Consistent with how
// vulnerability alerts already override schedule and minimumReleaseAge.
enabled: true,

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.

enabled: true is a global behavior change, not scoped to uv.

needs maintainers input on this @viceice @secustor

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yeah I can see how this can be regarded as too broad.

One way to make this cleaner could be to add a dedicated lockfile-only skipReason and have the OSV processor clear it when we need to push a fix bump.

@khvn26 khvn26 requested a review from RahulGautamSingh June 27, 2026 18:57
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.

2 participants