With the new hardening on blocking internal hosts with outbound HTTP
calls, we should build on top of this to ensure that the UX is better
when a preset is blocked.
We can do this by making sure that when `HOST_BLOCKED`, we report a more
targeted config validation error.
We can also make sure to pass around our `internalGrants`, similar to
how we currently allow an admin's `headers` are handled.
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As part of changes we've recently made to the merging of
`hostRules[].headers`, it highlighted that a repository - or a preset
it extends - could lead to a header an admin has configured for one host
to be sent to another.
This happened due to the way we additively merged i.e.
`Object.assign({}, ...matchedHeaders)`.
This doesn't require the repository to know a credential is being
set (for a specific host), or to act maliciously - any header of their
own for that host is enough to bring the administrator's masked one
back, with nothing logged or failing to show it happened.
To fix this, we can:
- apply admin headers last, as they are "trusted"
- stop repositories from being able to unset an admin-set header
- retain the existing logic for the "most specific rule" being used
- make sure that `trusted` isn't a field that could be injected by a
repository, and make sure we explicitly only set it where we know
we're using self-hosted administrator config
- make `filterAllowedHeaders` drop `headers` if every header name was
denied, so `{}` isn't returned and used to suppress headers when
merged
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
We previously enforced `allowedHeaders` by making sure that each
`hostRules.add()` call had `filterAllowedHeaders`.
This isn't super future proofed, and although we could add a linting
rule, we should instead enforce this by making sure that
`hostRules.add()` applies the filtering.
This also catches cases like host rules from `.npmrc` which wasn't
currently being filtered - albeit there was no means to bypass
`allowedHeaders`.
Moving `filterAllowedHeaders` into `lib/util` removes a dependency from
the global bootstrap and `config-validator` importing from
`lib/workers/repository/init/`.
While doing so, we can also make sure that:
- we log only one WARN for global `hostRules` being invalid, rather than
once per `repositories[]`
- `renovate-config-validator` validates a global config file's
`hostRules` against that file's own `allowedHeaders`, like a real run
would after parsing it
Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
As a further level of defence-in-depth for fixes on top of `allowedEnv`
and `allowedHeaders` enforcement, we can also make sure that we're
performing full config validation for the resolved configuration.
This allows us to report any configuration errors/warnings when we
include the full resolved configuration, without necessarily blocking
the full Renovate run, unless using `configValidationError`.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As an additional defence-in-depth, we can make sure that when applying
the `headers` configuration (from repo config, or presets) we
re-validate it.
We allow any admin-supplied configuration regardless, and then any
user-supplied settings are re-filtered according to `allowedHeaders`.
Due to the existing way that header merging incorrectly merges the repo
(or preset) `headers` over the admin config, we don't currently handle
this explicitly, unlike `filterAllowedEnv`.
If a user-supplied setting is filtered, we log a WARN message to inform
the user - and the admin - that this is ignored.
At this point, we don't try and explain which preset(s) this may have
come from, only that there is an issue.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
As an additional defence-in-depth, we can make sure that when applying
the `env` configuration (from repo config, or presets) we re-validate
it.
We allow any admin-supplied configuration regardless, and then any
user-supplied settings are re-filtered according to `allowedEnv`.
If a user-supplied setting is filtered, we log a WARN message to inform
the user - and the admin - that this is ignored.
At this point, we don't try and explain which preset(s) this may have
come from, only that there is an issue.
Co-authored-by: Claude Opus 4.8 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if
as errors in .oxlintrc.json and fix all 131 pre-existing violations
(91 no-else-return, 40 unicorn/no-lonely-if) across 98 files.
The no-else-return violations were fixed with the oxlint autofix
(iterated to a fixpoint, plus two else-if chains that required
--fix-dangerously) followed by Prettier formatting. One comment dropped
by the autofix in lib/modules/manager/pub/artifacts.ts was restored
manually. The unicorn/no-lonely-if violations were merged by hand,
preserving comments and coverage-ignore hints.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
As noted in #15827, it would be useful to log the "shallow"
configuration for a given repository - that is, the resolved
configuration, but without any Renovate internal presets being included.
This will be very useful for debugging, as it shows the final resulting
configuration, but without the - often very - verbose internal presets.
In the case that only this log line is shared, we can make sure to
reference the version of the Renovate CLI in the log line.
This requires building on top of changes in
6a4fa3f245 to be able to return a `merged`
and `unmerged` list of presets, and uses helpers from
c8f42e86b4, and
66b84dd12b to process the internal presets
accordingly.
Since we first worked on this, we've worked on improvements to caching
which should provide a require no additional performance overhead
performing this resolution twice.
This can also lead to being able to understand more clearly how Renovate
configuration is being used[0], as we have the final resolved configuration.
We want to make sure we don't try and merge or visit any internal
presets if we're not going to merge them, so we can avoid verbose
`config` or `visitedPresets` results.
[0]: https://www.jvt.me/posts/2024/04/14/renovate-config-sql/
* fix(config): resolve repository entry presets in correct order
* refactor: extract `applyHostRules` and `applyNpmrc` to functions
* Reuse applyHostRules in inherited.ts
* Fix test failure
* Improve resolvedRepoEntry log
* Coerce everything
* Fix another test coverage issue
As part of future changes, we want to log the shallow configuration (the
full resolved configuration, but without any internal Renovate
configuration presets), where we'll want to note which presets have not
been merged in.
Before that, we can start with an initial refactor to indicate which
have been merged, and return them.