* refactor(manager); add utility for creating Artifact Error messages
To prevent ignoring linting rules for nullish coalescing, as well as for
future changes that will use this helper, we can extract out a helper
function for this.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* fixup! refactor(manager); add utility for creating Artifact Error messages
---------
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fix(swift): allow Package.resolved pins without a `revision`
The swift manager's Package.resolved Zod schema requires
`state.revision: z.string()` on every pin. That is correct for
source-control pins (`kind: "remoteSourceControl"`), which always
have a git commit SHA, but wrong for SwiftPM Package Registry pins
(`kind: "registry"`) introduced by SE-0292: registry packages are
identified by a version alone and have no revision. As a result,
any Package.resolved that mixes source-control and registry pins
fails `PackageResolvedJson.safeParse`, `updateArtifacts` logs
`swift: could not parse Package.resolved` and returns `null`, and
Renovate silently stops writing lockfile updates on that repository.
This makes `state.revision` optional in the pin schema. The existing
`updateArtifacts` logic already guards the revision-replacement
branch with `if (newRevision)`, so registry pins are still safely
left untouched during source-control dep bumps.
Adds a regression test with a mixed-pins fixture. Before this change
that test panicked at parse time; after the change it demonstrates
the source-control pin gets updated and the registry pin is preserved
without gaining a spurious revision field.
Refs: #41534 (initial Package.resolved support, tested with
source-control pins only), #42303 (from: prefix strip).
* test(manager/swift): address review feedback on mixed-pins test
Per review on the Package.resolved mixed source-control/registry pins
test: inline the fixture into the test body, trim the comment to a
concise regression note, and assert on the parsed JSON with
toMatchObject instead of substring matching.
Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>
* test(manager/swift): assert full updateArtifacts result for mixed pins
Per review: replace the parse/find/toMatchObject assertions with a
single resolves.toEqual on the whole updateArtifacts result, comparing
against the expected Package.resolved output directly.
Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>
* test(manager/swift): trim mixed-pins regression comment
Apply review suggestion to shorten the comment to a single line.
Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>
---------
Co-authored-by: Claude (Cricut Security policy) <noreply@anthropic.com>
* feat: add regex support for gitIgnoredAuthors configuration
* feat: add tests for gitIgnoredAuthors regex handling in isBranchModified
* refactor: simplify ignored authors matching in isBranchModified function
* refactor: use for-of loop for ignored author filtering
* fix(git): treat non-regex gitIgnoredAuthors as exact strings
* fix(git): remove duplicate import of matchRegexOrGlobList
* fix(git): reorder import statements for consistency
* feat(git): enhance gitIgnoredAuthors handling with regex validation and logging
* feat(git): enhance gitIgnoredAuthors support for glob patterns and improve regex handling
* fix(git): add support for escaped glob patterns in matchRegexOrGlobList
* feat(git): update gitIgnoredAuthors documentation and improve regex handling for glob patterns
* fix(git): improve escaping of brackets and backslashes in glob pattern handling
* feat(git): normalize GitHub bot email addresses in ignored authors handling
* feat(tests): add custom author with brackets to file list in index.spec.ts
* feat(git): refactor ignored author handling to support regex normalization
* feat(git): enhance ignored authors handling to support regex patterns
* chore: retrigger ci
Allow osvVulnerabilityAlerts to match OSV sub-ecosystems such as
Packagist:https://packages.drupal.org/8, based on #40004. Adds a
negative test so unrelated prefixes like PackagistSomething do not match.
Co-authored-by: Stephan Zeidler <stephan@ramsalt.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(replacements): add replacements for dev-facing Comet packages
* fix: add current version matcher to rules
* fix: change dev-process-manager current version to >=3.0.0
As part of future changes in #45190, we have found that when using
GitHub Actions' dependency lockfile, the digest pinning is manged by the
lockfile, rather than being specified in the package file itself.
To avoid a "flip flop" where using the manager removes the digest from
the package file (relying on the lockfile itself) and then a `pinDigest`
update re-adds it to the package file, we can instead follow how
`digestOneAndOnly` works and add a means to note
`digestManagedExternally`.
This isn't currently used, but allows an opt out for github-actions in
the future.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* feat(deps): update ghcr.io/renovatebot/base-image docker tag to v13.84.0
| datasource | package | from | to |
| ---------- | ------------------------------ | ------- | ------- |
| docker | ghcr.io/renovatebot/base-image | 13.83.0 | 13.84.0 |
* feat(util/exec): add support for `gh` tool
As a prerequisite for #44753 and #45190, we need to support the `gh`
CLI.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
`cargo2npm` exists because a bare `1.2.3` in Cargo means `^1.2.3` and
`0.4` means `^0.4`, since caret requirements are the default. Every
range-consuming function in this module converts through it: `isValid`,
`matches`, `isLessThanRange`, `getSatisfyingVersion`,
`minSatisfyingVersion` and `getNewValue`.
`subset` and `intersects` did not. The exported `api` is built from a
`...npm` spread and never overrode them, so they received Cargo syntax
and interpreted it as semver syntax. Read that way, `1.70` means
`1.70.x` rather than `^1.70`:
subset('1.70', '1.63') was false, is now true
intersects('1.70', '1.63') was false, is now true
intersects('1.63', '1.70') was false, is now true
`subset` is called by `applyConstraintsFiltering`, so repositories using
`constraintsFiltering: 'strict'` had crate releases dropped whenever the
release constraint differed from the configured one. `intersects` has no
caller in this repository today, but it is part of `VersioningApi` and
was wrong in the same way.
Both are now wrapped the way `composer` does it, including the
`try`/`catch`, because the underlying semver calls throw on ranges they
cannot parse.
The module had no tests for either function, which is why this was not
caught. Both are now covered, including the throwing path.
The `rust` tool was resolved via the `github-tags` datasource on
`rust-lang/rust` with the default (semver) versioning. That meant the
release channel values rustup actually accepts were not understood.
Switch all three managers to the `rust-version` datasource, which
declares `rust-release-channel` as its `defaultVersioning`, matching the
`rust-toolchain` manager and `lib/util/exec/containerbase.ts`.
`packageName` becomes `rust` rather than the `rust-lang/rust` owner/repo
slug, which is meaningless for this datasource. It is set rather than
omitted because mise would otherwise fall back to the backend-prefixed
depName, yielding `core:rust` / `asdf:rust` as the package name.
No explicit `versioning` is set: the datasource default already applies,
and the convention in these files is to set `versioning` only to
override a datasource default.
Behaviour change: `nightly-<date>` pins were previously skipped as
`invalid-value` and now update. `stable`, `beta` and `nightly` are now
recognised as ranges rather than flagged invalid, but still only resolve
to a concrete version under `rangeStrategy: pin`.
The manager emitted `logger.warn` four times during extraction and
returned `null` for content that is valid but not updatable. A
`rust-toolchain.toml` using `path` instead of `channel` is a legitimate
file, yet it failed schema validation and produced a maintainer-facing
warning.
Per the logging guidance in `docs/development/best-practices.md`, WARN
is consumed by metrics and error catching services, so it should not
fire for user content Renovate simply cannot update. The manager guide
also asks for a `skipReason` rather than silently dropping a dependency.
The schema now accepts an optional `channel` and an optional `path`, and
extraction reports:
- `invalid-version` when a channel cannot be parsed
- `path-dependency` when the file points at a local toolchain
- `unspecified-version` when neither field is set
`channel` takes precedence when both are present, since rustup rejects
that combination and `channel` is the actionable field.
Files that are not toolchain files at all still return `null`: TOML that
does not parse, TOML without a `[toolchain]` table, and legacy plain
text files that are empty or hold more than one line. The file pattern
matches any file named `rust-toolchain`, so these are treated as false
matches. All remaining logs are DEBUG.
As part of future changes, it makes it easier to work with the resulting
types, because it's clear when they are optional/required.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
When executing commands for `binarySource=docker`, we have two areas
that a command could have shell expansion/injection:
- on the host (when constructing the `bash -l -c`)
- in the container (when running a manager-specific command)
When constructing the host's command, we previously would escape the
`"`, which allows Bash syntax for `${VAR}` and `$(...)` syntax inside
it.
While managers use `quote()` to make the inputs safer, the use of `"`
around that would not provide any protection, and lead to cases where
the `quote()` could be expanded on the host, before `docker run`
executes.
After recent changes to each manager - and removal of `shell: true` -
this doesn't seem to be exploitable, but this hardens it further.
Additionally, we never escaped `\`, so a value containing `\"` produces
a command that `shlex.split` rejects, and the update fails rather than
running.
Instead, we can quote the whole `-c` argument with `quote()`, which
round-trips through both `shlex.split` - the default, no-shell path - and
a real shell.
This removes the `lgtm [js/incomplete-sanitization]` suppression as
we're now correctly sanitising this.
Note this doesn't remove the need for the managers to quote their own
values, as the second area above is still a real shell.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
To prevent the possibility of a npm package name including shell
metacharacters (which is unlikely, but potentially possible through a
well-crafted payload), which could lead to command execution, we can
make sure they are quoted appropriately.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
A malicious Host Rule could be crafted to inject shell metacharacters
which could lead to command execution, we can make sure they are quoted
appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
A malicious Host Rule could be crafted to inject shell metacharacters
which could lead to command execution, we can make sure they are quoted
appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
To prevent the possibility of the `distributionType` in a given
repository including shell metacharacters, which could lead to command
execution, we can make sure they are quoted appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
To prevent the possibility of the `distributionUrl` in a given
repository including shell metacharacters, which could lead to command
execution, we can make sure they are quoted appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
To prevent the possibility of a Go module name including
shell metacharacters (which is unlikely, but potentially possible
through a well-crafted payload), which could lead to command execution,
we can make sure they are quoted appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
To prevent the possibility of an `organization` or `token` including
shell metacharacters, which could lead to command execution, we can make
sure they are quoted appropriately.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As part of future changes, we'll add options that do not require the
Global option to take precedence and/or be used as an upper limit.
To make this clearer, we can split out the options into Global and Repo
variants.
If a proxy URL appears to have a password component in it, we should
make sure that this is sanitised.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* chore(util): note that `httpsCertificate` and `httpsCertificateAuthority` aren't secret
Although we're currently treating them as such, they're not technically
unsafe to appear in the logs, as a Certificate (and the authority) are
public.
* fix(util/host-rules): sanitise TLS credential fields in hostRules
We previously noted that the `httpsPrivateKey`, `httpsCertificate`, and
`httpsCertificateAuthority` fields would be marked as confidential, but
we weren't correctly sanitising them.
We can make sure that these fields are correctly flagged as secret
("confidential") and that they need to be sanitised when referenced.
Although the `httpsCertificate` and `httpsCertificateAuthority` aren't
secret, we can keep them sanitised for consistency with how we've
currently documented them as being sanitised.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* test(util/host-rules): ensure that all secret fields are marked as secret
As a way to make sure that new fields being added `HostRule`s are
considered as to whether the field should be marked as secret
("confidential") or not, we can add a test (and a compile-time
exhaustive check) to validate that `redactedFields` and
`confidentialFields` are kept in sync.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
---------
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As we shouldn't really be using it, we should flag up usages more
clearly.
In cases where we do need to specify this - when
`allowShellExecutorForPostUpgradeCommands` is set - then we can disable
the rule.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
As this is the only place in the codebase we're currently doing this, we
should remove the usage of `shell` semantics for file redirection, which
isn't needed.
Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
* refactor(manager/github-actions): return dependency arrays from community `with:` schemas
A `withSchema` now yields `PackageDependency[]` directly, instead of a
`{ val, ...meta }` object whose extra fields were merged in through an untyped
`Record<string, unknown>`. Schemas describe the dependency they find, and a
single step may yield more than one.
`isInvalid` moves out of `CommunityActionConfig` into `valSchema`, its only
caller. The config fields are now applied to every dependency a schema yields.
No behavior change.
* feat(manager/github-actions): support `pnpm/setup`
`pnpm/setup` replaces `pnpm/action-setup` for pnpm 11+. Its `version:` input
resolves as the `pnpm` package, and its `runtime:` input as the JavaScript
runtime to install - `node`, `bun` or `deno`, named as `<name>@<version>` to
match pnpm's `packageManager` field syntax.
An unknown runtime name is skipped as `invalid-name`, so a typo does not pass
silently.