Fix high-severity npm transitive dependency vulnerabilities via pnpm … (#48139)

* Fix high-severity npm transitive dependency vulnerabilities via pnpm overrides (#47657)

Apply pnpm.overrides in js/package.json to force patched versions of
vulnerable transitive dependencies:

- picomatch ^2.3.1 → ^2.3.2 (ReDoS via extglob quantifiers)
- flatted ^3.2.9 → ^3.4.2 (Prototype Pollution and unbounded recursion DoS)
- minimatch ~3 → ^3.1.4 (multiple ReDoS vectors)
- minimatch ~9 → ^9.0.7 (ReDoS via repeated wildcards)
- @isaacs/brace-expansion ^5 → ^5.0.1 (uncontrolled resource consumption)
- serialize-javascript ^6 → ^7.0.3 (RCE via RegExp.flags)

pnpm.overrides is used here because none of the direct dependencies that
pull in these transitive packages have released fixes upstream yet:

- wireit 0.14.12 (latest stable) → picomatch 2.3.1 via chokidar/micromatch
- eslint 9.x → flatted 3.3.3 via flat-cache, minimatch 3.1.2
- mocha 11.x → serialize-javascript 6.0.2
- vite-plugin-dts 4.x → minimatch 9.0.5, @isaacs/brace-expansion 5.0.0

Since the vulnerable ranges (e.g. ^2.3.1, ^3.2.9) already permit the
patched versions, overrides simply force pnpm to resolve to the fixed
minor/patch release rather than the previously locked version.

Signed-off-by: Bruno Oliveira da Silva <bruno@abstractj.com>
(cherry picked from commit e556494cec)

* Fix linting errors.

Signed-off-by: Stan Silvert <ssilvert@redhat.com>

---------

Signed-off-by: Bruno Oliveira da Silva <bruno@abstractj.com>
Signed-off-by: Stan Silvert <ssilvert@redhat.com>
Co-authored-by: Bruno Oliveira da Silva <bruno@abstractj.com>
This commit is contained in:
Stan Silvert
2026-04-17 05:01:31 -04:00
committed by GitHub
parent 1aa2bdf331
commit 8e46047410
10 changed files with 2494 additions and 1858 deletions
@@ -78,8 +78,7 @@ export const LogoutPanel = ({
label={t("frontchannelLogoutUrl")}
labelIcon={t("frontchannelLogoutUrlHelp")}
rules={{
validate: (uri) =>
validateUrl(uri, t("frontchannelUrlInvalid").toString()),
validate: (uri) => validateUrl(uri, t("frontchannelUrlInvalid")),
}}
/>
)}
@@ -105,8 +104,7 @@ export const LogoutPanel = ({
label={t("backchannelLogoutUrl")}
labelIcon={t("backchannelLogoutUrlHelp")}
rules={{
validate: (uri) =>
validateUrl(uri, t("backchannelUrlInvalid").toString()),
validate: (uri) => validateUrl(uri, t("backchannelUrlInvalid")),
}}
/>
<FormGroup
@@ -33,7 +33,9 @@ const EmptyButton = ({
<Button
data-testid={`create-${permissionType}`}
className={
disabled ? "keycloak__permissions__empty_state " : "" + "pf-v5-u-m-sm"
disabled
? "keycloak__permissions__empty_state pf-v5-u-m-sm"
: "pf-v5-u-m-sm"
}
variant="secondary"
onClick={() =>
+1 -4
View File
@@ -440,10 +440,7 @@ export const AdminEvents = ({ resourcePath }: AdminEventsProps) => {
}
>
{operationTypes?.map((option) => (
<SelectOption
key={option.toString()}
value={option}
>
<SelectOption key={option} value={option}>
{option}
</SelectOption>
))}
@@ -479,7 +479,7 @@ export default function NewClientPolicy() {
required: t("required"),
validate: (value) =>
policies.some((policy) => policy.name === value)
? t("createClientProfileNameHelperText").toString()
? t("createClientProfileNameHelperText")
: true,
}}
/>
@@ -41,20 +41,20 @@ export const RevocationModal = ({
addAlert(t("noAdminUrlSet"), AlertVariant.warning);
} else if (failedCount > 0) {
addAlert(
t("" + prefixKey + "Success", {
t(`${prefixKey}Success`, {
successNodes: result.successRequests,
}),
AlertVariant.success,
);
addAlert(
t("" + prefixKey + "Fail", {
t(`${prefixKey}Fail`, {
failedNodes: result.failedRequests,
}),
AlertVariant.danger,
);
} else {
addAlert(
t("" + prefixKey + "Success", {
t(`${prefixKey}Success`, {
successNodes: result.successRequests,
}),
AlertVariant.success,
@@ -138,7 +138,7 @@ export const LdapSettingsGeneral = ({
control={form.control}
render={({ field }) => (
<KeycloakSelect
isDisabled={!!vendorEdit}
isDisabled={vendorEdit}
toggleId="kc-vendor"
onToggle={() => setIsVendorDropdownOpen(!isVendorDropdownOpen)}
isOpen={isVendorDropdownOpen}
@@ -161,7 +161,7 @@ export const ResetPasswordDialog = ({
onChange(e);
if (passwordConfirmation !== e.currentTarget.value) {
setError("passwordConfirmation", {
message: t("confirmPasswordDoesNotMatch").toString(),
message: t("confirmPasswordDoesNotMatch"),
});
} else {
clearErrors("passwordConfirmation");
@@ -187,8 +187,7 @@ export const ResetPasswordDialog = ({
{...register("passwordConfirmation", {
required: true,
validate: (value) =>
value === password ||
t("confirmPasswordDoesNotMatch").toString(),
value === password || t("confirmPasswordDoesNotMatch"),
})}
/>
{errors.passwordConfirmation && (
@@ -257,7 +257,7 @@ function DataTable<T>({
rows[index + 1].cells.length === 0
? undefined
: {
isExpanded: !!expandedRows[index],
isExpanded: expandedRows[index] ?? false,
rowIndex: index,
expandId: "expandable-row-",
onToggle: (_, rowIndex, isOpen) => {
@@ -277,7 +277,7 @@ function DataTable<T>({
/>
</Tr>
) : (
<Tr isExpanded={!!expandedRows[index - 1]}>
<Tr isExpanded={expandedRows[index - 1] ?? false}>
<Td />
<Td colSpan={columns.length}>
<ExpandableRowContent>
+20 -1
View File
@@ -64,6 +64,14 @@
"patternfly-bootstrap-combobox",
"patternfly-bootstrap-treeview"
],
"overrides": {
"picomatch@^2": "^2.3.2",
"flatted": "^3.4.2",
"minimatch@~3": "^3.1.4",
"minimatch@~9": "^9.0.7",
"@isaacs/brace-expansion@^5": "^5.0.1",
"serialize-javascript": "^7.0.3"
},
"onlyBuiltDependencies": [
"@swc/core",
"esbuild"
@@ -71,5 +79,16 @@
},
"lint-staged": {
"*.{js,jsx,mjs,ts,tsx}": "eslint --cache --fix"
}
},
"author": {
"name": "Red Hat, Inc.",
"url": "https://www.keycloak.org/"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/keycloak/keycloak.git",
"directory": "js/"
},
"homepage": "https://www.keycloak.org/"
}
+2459 -1838
View File
File diff suppressed because it is too large Load Diff