Automated Patch Intelligence for Security Engineers
CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause : The vm2 sandbox failed to properly denylist certain Node.js built-in modules and their subpaths, specifically 'process' and 'inspector/promises'. This allowed an attacker to bypass the sandbox's security mechanisms by requiring these modules, which provide direct access to host system capabilities.
Impact : An attacker could execute arbitrary code on the host system, completely escaping the sandbox environment and gaining full control over the application running the vm2 instance.
Diff
--- a/lib/builtin.js
+++ b/lib/builtin.js
@@ -69,6 +87,7 @@ const DANGEROUS_BUILTINS = new Set([
'vm',
'repl',
'inspector',
+ 'process',
// Host-process abort DoS: `trace_events.createTracing({categories: [...]})`
// asserts `args[0]->IsArray()` in C++; the array crosses the bridge as a
// Proxy, which fails the assertion and aborts the entire host process.
@@ -83,8 +102,21 @@ const DANGEROUS_BUILTINS = new Set([
'wasi'
]);
+// SECURITY (GHSA-rp36-8xq3-r6c4): Family-prefix denylist check. inspector and
+// inspector/promises must share fate; same for any future subpath under a
+// dangerous family. Also strips the node: URL-style prefix so
+// node:process and node:inspector/promises cannot bypass via spelling.
+function isDangerousBuiltin(key) {
if (typeof key !== 'string') return false;
if (key.startsWith('node:')) key = key.slice(5);
if (DANGEROUS_BUILTINS.has(key)) return true;
const slash = key.indexOf('/');
if (slash > 0 && DANGEROUS_BUILTINS.has(key.slice(0, slash))) return true;
return false;
+}
const BUILTIN_MODULES = (nmod.builtinModules || Object.getOwnPropertyNames(process.binding('natives')))
.filter(s=>!s.startsWith('internal/') && !DANGEROUS_BUILTINS.has(s));
.filter(s=>!s.startsWith('internal/') && !isDangerousBuiltin(s));Fix : The patch expands the denylist of dangerous built-in modules to include 'process' and implements a family-based matching function, `isDangerousBuiltin`, to block subpaths like 'inspector/promises'. It also strips the 'node:' prefix from module names to prevent bypasses via alternative spellings, ensuring that these critical modules are never accessible from within the sandbox.
CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 10.0 · 2026-05-11 · JavaScript
@nyariv/sandboxjs · Pattern: TYPE_CONFUSION→BYPASS · 3x across ecosystem
Root cause : The sandbox environment in SandboxJS failed to restrict access to sensitive JavaScript properties like 'caller', 'callee', and 'arguments'. These properties, when accessed from within a sandboxed function, could leak references to the internal execution context or global objects, effectively allowing an attacker to break out of the sandbox.
Impact : An attacker could escape the JavaScript sandbox, gaining access to the host environment and potentially executing arbitrary code or accessing sensitive resources outside the intended sandboxed scope.
Diff
--- a/src/executor/ops/prop.ts
+++ b/src/executor/ops/prop.ts
@@ -93,12 +93,15 @@ addOps<unknown, PropertyKey>(LispType.Prop, ({ done, a, b, obj, context, scope,
}
}
const val = a[b as keyof typeof a] as unknown;
if (typeof a === 'function') {
if (b === 'prototype' && !context.ctx.sandboxedFunctions.has(a)) {
throw new SandboxAccessError(Access to prototype of global object is not permitted);
}
if (['caller', 'callee', 'arguments'].includes(b as string)) {
throw new SandboxAccessError(`Access to '${b as string}' property is not permitted`);
}
}
const val = a[b as keyof typeof a] as unknown;
if (b === 'proto' && !context.ctx.sandboxedFunctions.has(val?.constructor as any)) {
throw new SandboxAccessError(Access to prototype of global object is not permitted);Fix : The patch explicitly disallows access to the 'caller', 'callee', and 'arguments' properties when a property is accessed on a function within the sandboxed environment. It introduces a check that throws a SandboxAccessError if an attempt is made to access these forbidden properties.
CRITICAL 10.0 · 2026-05-08 · Go
github.com/free5gc/smf · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : The free5GC SMF's UPI management interface was not protected by any authentication middleware. This allowed unauthenticated requests to reach the underlying handlers for reading and writing topology information.
Impact : An unauthenticated attacker could perform read and write operations on the SMF's UPI topology, potentially disrupting network operations or gaining unauthorized access to sensitive network configuration.
Diff
--- a/internal/sbi/server.go
+++ b/internal/sbi/server.go
@@ -74,6 +74,10 @@ func newRouter(s *Server) *gin.Engine {
upiGroup := router.Group(factory.UpiUriPrefix)
upiAuthCheck := util_oauth.NewRouterAuthorizationCheck(models.ServiceName_NSMF_OAM)
upiGroup.Use(func(c *gin.Context) {
upiAuthCheck.Check(c, smf_context.GetSelf())
})
upiRoutes := s.getUPIRoutes()
applyRoutes(upiGroup, upiRoutes)Fix : The patch introduces an authentication check for the UPI management interface. It adds a new router authorization check using `util_oauth.NewRouterAuthorizationCheck` and applies it as middleware to the `upiGroup` router, ensuring all requests to this interface are authenticated.
CRITICAL 10.0 · 2026-05-07 · Go
github.com/enchant97/note-mark/backend · Pattern: INSECURE_DEFAULT→CONFIG · 12x across ecosystem
Root cause : The application allowed a JWT secret to be configured without a minimum length validation. This meant that a short, easily guessable secret could be used, making JWT tokens vulnerable to brute-force attacks.
Impact : An attacker could brute-force the weak JWT secret, forge valid authentication tokens, and achieve full account takeover for any user, including administrative accounts.
Diff
- JWTSecret Base64Decoded `env:"JWT_SECRET,notEmpty"`
+ JWTSecret Base64Decoded `env:"JWT_SECRET,notEmpty" validate:"gte=32"`Fix : The patch adds a validation rule to the `JWTSecret` configuration field, ensuring that the secret must have a minimum length of 32 characters. This significantly increases the entropy and makes brute-forcing infeasible.
CRITICAL 10.0 · 2026-04-22 · Go
github.com/jkroepke/openvpn-auth-oauth2 · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : The application incorrectly returned 'FUNC_SUCCESS' even when a client's authentication was explicitly denied or an error occurred during the authentication process. This misinterpretation of the return code by OpenVPN led to clients being granted access despite failing authentication.
Impact : An attacker could gain unauthorized access to the VPN without providing valid credentials, effectively bypassing the entire authentication mechanism.
Diff
--- a/lib/openvpn-auth-oauth2/openvpn/handle.go
+++ b/lib/openvpn-auth-oauth2/openvpn/handle.go
@@ -144,7 +144,7 @@ func (p *PluginHandle) handleAuthUserPassVerify(clientEnvList **c.Char, perClien
slog.Any("err", err),
)
- return c.OpenVPNPluginFuncSuccess
+ return c.OpenVPNPluginFuncError
case management.ClientAuthPending:
pendingRespCh, err := p.managementClient.RegisterPendingPoller(currentClientID)Fix : The patch changes the return value from 'c.OpenVPNPluginFuncSuccess' to 'c.OpenVPNPluginFuncError' when a client's authentication is denied or an error occurs during the process. This ensures that OpenVPN correctly interprets the authentication failure and denies access.
CRITICAL 10.0 · 2026-04-14 · PHP
wwbn/avideo · Pattern: UNSANITIZED_INPUT→XSS · 51x across ecosystem
Root cause : The application's WebSocket broadcast relay allowed unauthenticated users to inject arbitrary JavaScript code into messages. Specifically, the 'autoEvalCodeOnHTML' field and the 'callback' field in WebSocket messages were not properly sanitized or validated before being relayed to other clients, which would then execute the injected code via client-side eval() sinks.
Impact : An attacker could achieve unauthenticated cross-user JavaScript execution, leading to session hijacking, data theft, defacement, or other malicious activities on the client-side for any user connected to the WebSocket.
Diff
- //_log_message("onMessage:msgObj: " . json_encode($json));
+ //_log_message("onMessage:msgObj: " . json_encode($json));
+ // Strip eval-able fields from browser/guest messages.
+ if (empty($msgObj->isCommandLineInterface) && ($msgObj->sentFrom ?? '') !== 'php') {
+ if (is_array($json['msg'] ?? null)) {
+ unset($json['msg']['autoEvalCodeOnHTML']);
+ }
+ if (isset($json['callback']) && !preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', (string)$json['callback'])) {
+ unset($json['callback']);
+ }
+ }
if (!empty($msgObj->send_to_uri_pattern)) {
$this->msgToSelfURI($json, $msgObj->send_to_uri_pattern);
} else if (!empty($json['resourceId'])) {Fix : The patch introduces input validation and sanitization for WebSocket messages. It specifically removes the 'autoEvalCodeOnHTML' field from messages originating from browsers or guests and ensures that the 'callback' field, if present, adheres to a strict alphanumeric and underscore pattern, effectively preventing arbitrary JavaScript injection.
CRITICAL 10.0 · 2026-04-10 · Go
github.com/daptin/daptin · Pattern: PATH_TRAVERSAL→FILE_WRITE · 25x across ecosystem
Root cause : The application allowed user-supplied filenames and archive entry names to be used directly in file system operations (e.g., `filepath.Join`, `os.OpenFile`, `os.MkdirAll`) without sufficient sanitization. This enabled attackers to manipulate file paths using `../` sequences or absolute paths.
Impact : An unauthenticated attacker could write arbitrary files to arbitrary locations on the server's file system, potentially leading to remote code execution, data corruption, or denial of service. In the case of Zip Slip, files within an uploaded archive could be extracted outside the intended directory.
Diff
--- a/server/asset_upload_handler.go
+++ b/server/asset_upload_handler.go
@@ -67,6 +67,13 @@ func AssetUploadHandler(cruds map[string]*resource.DbResource) func(c *gin.Conte
c.AbortWithError(400, errors.New("filename query parameter is required"))
return
}
+ // Strip path traversal from filename
+ if fileName != "" {
+ fileName = filepath.Clean(fileName)
+ for strings.HasPrefix(fileName, "..") {
+ fileName = strings.TrimPrefix(strings.TrimPrefix(fileName, ".."), string(filepath.Separator))
+ }
+ }
// Validate table and column
dbResource, ok := cruds[typeName]
if !ok || dbResource == nil {Fix : The patch introduces robust path sanitization by using `filepath.Clean` and then iteratively stripping any leading `..` components from user-supplied filenames and archive entry names. This ensures that all file system operations are constrained to the intended directories.
CRITICAL 10.0 · 2026-04-10 · JavaScript
axios · Pattern: UNSANITIZED_INPUT→HEADER · 8x across ecosystem
Root cause : The Axios library did not properly sanitize header values, allowing newline characters (CRLF) to be injected. This meant that an attacker could append arbitrary headers or even inject a new HTTP request body by including these characters in a user-controlled header value.
Impact : An attacker could inject arbitrary HTTP headers, potentially leading to SSRF (Server-Side Request Forgery) against cloud metadata endpoints or other internal services, and could also manipulate the request body.
Diff
--- a/lib/core/AxiosHeaders.js
+++ b/lib/core/AxiosHeaders.js
@@ -5,18 +5,49 @@ import parseHeaders from '../helpers/parseHeaders.js';
const $internals = Symbol('internals');
+const isValidHeaderValue = (value) => !/[
]/.test(value);
+
+function assertValidHeaderValue(value, header) {
if (value === false || value == null) {
return;
}
if (utils.isArray(value)) {
value.forEach((v) => assertValidHeaderValue(v, header));
return;
}
if (!isValidHeaderValue(String(value))) {
throw new Error(Invalid character in header content ["${header}"]);
}
+}
function normalizeValue(value) {
if (value === false || value == null) {
return value;
}
return utils.isArray(value)
? value.map(normalizeValue)
: String(value).replace(/[
]+$/, '');
return utils.isArray(value) ? value.map(normalizeValue) : stripTrailingCRLF(String(value));
}
function parseTokens(str) {
@@ -98,6 +129,7 @@ class AxiosHeaders {
_rewrite === true ||
(_rewrite === undefined && self[key] !== false)
) {
assertValidHeaderValue(_value, _header);
self[key || _header] = normalizeValue(_value);
}
}Fix : The patch introduces a `isValidHeaderValue` function to explicitly check for and disallow newline characters (CRLF) in header values. It also adds an `assertValidHeaderValue` function to enforce this validation before header values are set, preventing header injection.
CRITICAL 9.9 · 2026-06-09 · PHP
pheditor/pheditor · Pattern: UNSANITIZED_INPUT→COMMAND · 39x across ecosystem
Root cause : The application was directly embedding user-supplied input from the 'dir' parameter into a shell command without proper sanitization. This allowed an attacker to inject arbitrary shell commands by manipulating the 'dir' value.
Impact : An attacker could execute arbitrary operating system commands on the server, leading to full system compromise, data exfiltration, or denial of service.
Diff
- $output = shell_exec((empty($dir) ? null : 'cd ' . $dir . ' && ') . $command . ' && echo \ ; pwd');
+ $output = shell_exec((empty($dir) ? null : 'cd ' . escapeshellarg($dir) . ' && ') . $command . ' && echo \ ; pwd');Fix : The patch addresses the vulnerability by wrapping the user-supplied 'dir' parameter with `escapeshellarg()` before it is used in the `shell_exec()` function. This ensures that any special characters in the 'dir' value are properly escaped, preventing command injection.
CRITICAL 9.9 · 2026-06-08 · Go
github.com/juev/nebula-mesh · Pattern: PRIVILEGE_ESCALATION→ROLE · 20x across ecosystem
Root cause : The application used a cached context value for `actorIsAdmin` checks, which meant that if an operator's role was downgraded from 'admin' to a regular user, their active session would still incorrectly reflect them as an administrator. This allowed them to bypass authorization checks on various API endpoints.
Impact : An attacker could maintain administrative privileges even after their role was revoked, enabling them to perform actions such as managing other operators, accessing audit logs, listing all CAs, and other sensitive operations that should be restricted to active administrators.
Diff
--- a/internal/api/authz.go
+++ b/internal/api/authz.go
@@ -8,10 +8,29 @@ import (
"github.com/juev/nebula-mesh/internal/store"
)
+// isActiveAdmin re-fetches the captured-ctx actor and reports whether
+// they are still an active admin.
+func (s *Server) isActiveAdmin(ctx context.Context) bool {
captured := ActorOf(ctx)
if captured == nil {
return false
}
fresh, err := s.store.GetOperator(ctx, captured.ID)
if err != nil {
if !errors.Is(err, store.ErrNotFound) {
s.logger.Error("isActiveAdmin: store lookup", "operator", captured.ID, "error", err)
}
return false
}
return fresh.Status == models.OperatorStatusActive && fresh.Role == "admin"
+}
// actorOwnsCA returns true if the actor in ctx is admin, or owns the CA with caID.
// Returns (false, nil) for empty caID or ErrNotFound. Errors only for unexpected DB errors.
func (s *Server) actorOwnsCA(ctx context.Context, caID string) (bool, error) {
if actorIsAdmin(ctx) {
if s.isActiveAdmin(ctx) {
return true, nil
}
if caID == "",Fix : A new function `isActiveAdmin` was introduced to re-fetch the operator's status and role directly from the database for each authorization check. All calls to the old `actorIsAdmin` function were replaced with `s.isActiveAdmin(ctx)` to ensure that administrative checks are always based on the most current operator status.
CRITICAL 9.9 · 2026-05-05 · Python
firefighter-incident · Pattern: SSRF→CLOUD_METADATA · 1x across ecosystem
Root cause : The application's `jira_bot` endpoint allowed unauthenticated users to provide arbitrary URLs for attachments. These URLs were then fetched by the server without proper validation, enabling an attacker to direct the server to make requests to internal network resources or cloud metadata endpoints.
Impact : An attacker could perform Server-Side Request Forgery (SSRF) attacks, leading to the theft of IAM credentials or access to other sensitive internal services and data.
Diff
--- a/src/firefighter/raid/serializers.py
+++ b/src/firefighter/raid/serializers.py
@@ -56,6 +59,58 @@
logger = logging.getLogger(__name__)
+ATTACHMENT_MAX_COUNT = 10
+ATTACHMENT_URL_MAX_LENGTH = 2048
+ATTACHMENT_ALLOWED_SCHEMES = frozenset({"http", "https"})
+
+
+def parse_attachment_urls(raw: str | None) -> list[str]:
"""Normalise the attachments payload sent by Landbot into a list of URLs.
Landbot historically sends a Python-stringified list (e.g. "['https://a', 'https://b']")
rather than a JSON array. This helper tolerates that legacy format along with
a plain comma-separated string or a single URL.
"""
if not raw:
return []
stripped = raw.replace("[", "").replace("]", "").replace("'", "").replace('"', "")
return [item.strip() for item in stripped.split(",") if item.strip()]
+def _validate_attachment_url(url: str) -> None:
if len(url) > ATTACHMENT_URL_MAX_LENGTH:
msg = f"Attachment URL exceeds {ATTACHMENT_URL_MAX_LENGTH} characters."
raise serializers.ValidationError(msg)
parsed = urlparse(url)
if parsed.scheme not in ATTACHMENT_ALLOWED_SCHEMES:
msg = f"Attachment URL scheme '{parsed.scheme}' is not allowed."
raise serializers.ValidationError(msg)
host = parsed.hostname
if not host:
raise serializers.ValidationError("Attachment URL is missing a host.")
try:
addr_infos = socket.getaddrinfo(host, None)
except socket.gaierror as err:
msg = f"Attachment URL host '{host}' could not be resolved."
raise serializers.ValidationError(msg) from err
SSRF guard: reject any host resolving to a non-routable address so the
fetch in add_attachments_to_issue can never reach internal services
(cloud metadata endpoint, RFC1918 networks, loopback).
for info in addr_infos:
ip = ipaddress.ip_address(info[4][0])
if (
ip.is_private
or ip.is_loopback
or ip.is_link_local
or ip.is_reserved
or ip.is_multicast
or ip.is_unspecified
):
raise serializers.ValidationError(
"Attachment URL host resolves to a private, loopback or link-local address."
)
class IgnoreEmptyStringListField(serializers.ListField):
def to_internal_value(self, data: list[Any] | Any) -> list[str]:
# Check if data is a listFix : The patch introduces authentication for the `jira_bot` endpoint, requiring a bearer token. Additionally, it implements robust URL validation for attachments, including scheme checks, host resolution, and a critical SSRF guard that rejects URLs resolving to private, loopback, link-local, reserved, multicast, or unspecified IP addresses.
CRITICAL 9.8 · 2026-06-11 · PHP
codeigniter4/framework · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause : The vulnerability existed because the `ext_in` validation rule only checked the guessed file extension, which could be manipulated by an attacker. The `guessExtension()` method might return an empty string or an incorrect extension if the file's MIME type or content was malformed, allowing a malicious file with a dangerous extension (e.g., .php) to bypass the intended extension whitelist.
Impact : An attacker could upload files with disallowed extensions, potentially leading to remote code execution if the server is configured to execute scripts based on their extension, or other forms of system compromise.
Diff
- if (! in_array($file->guessExtension(), $params, true)) {
+ $clientExtension = strtolower($file->getClientExtension());
+
+ if ($clientExtension === '' || ! in_array($clientExtension, $params, true)) {
+ return false;
+ }
+
+ if ($file->guessExtension() !== $clientExtension) {
return false;
}Fix : The patch enhances the `ext_in` validation rule by explicitly checking both the client-provided file extension (`getClientExtension()`) and comparing it with the guessed extension (`guessExtension()`). It ensures that the client extension is not empty and is part of the allowed list, and that the guessed extension matches the client extension, preventing bypasses through manipulated file types.
CRITICAL 9.8 · 2026-05-29 · JavaScript
vm2 · Pattern: TYPE_CONFUSION→BYPASS · 3x across ecosystem
Root cause : The vm2 sandbox failed to properly isolate WebAssembly JavaScript Promise Integration (JSPI) Promises. These Promises, when created within the sandbox, had their prototype chain directly linked to the host realm's `Promise.prototype`, bypassing the sandbox's proxy mechanisms and overrides. This allowed an attacker to manipulate the `constructor` property of a JSPI Promise, leading to the creation of host-realm Promise resolution/rejection functions that executed attacker-controlled code in the host context.
Impact : An attacker could execute arbitrary code in the host environment, effectively escaping the vm2 sandbox and gaining full control over the system running the sandboxed code.
Diff
--- a/lib/setup-sandbox.js
+++ b/lib/setup-sandbox.js
@@ -473,6 +473,57 @@ if (typeof WebAssembly !== 'undefined' && WebAssembly.JSTag !== undefined) {
localReflectDeleteProperty(WebAssembly, 'JSTag');
}
+if (typeof WebAssembly !== 'undefined') {
// SECURITY (GHSA-6j2x-vhqr-qr7q): WebAssembly.promising returns Promises with
// host-realm Promise.prototype in their [[Prototype]] chain. No sandbox-side
// override and no bridge proxy can intercept method dispatch on such objects.
if (typeof WebAssembly.promising !== 'undefined') {
localReflectDeleteProperty(WebAssembly, 'promising');
}
// SECURITY (GHSA-6j2x-vhqr-qr7q): WebAssembly.Suspending is required to satisfy
// the suspending-import slot in any JSPI module. Removing it alone closes the
// instantiation half of the chain; removing .promising closes the export half.
if (typeof WebAssembly.Suspending !== 'undefined') {
localReflectDeleteProperty(WebAssembly, 'Suspending');
}
+}
if (
!localReflectDefineProperty(global, 'VMError', {Fix : The patch removes `WebAssembly.promising` and `WebAssembly.Suspending` from the sandbox environment. By deleting these properties, the sandbox prevents the creation of JSPI Promises that exhibit the problematic cross-realm prototype behavior, thereby eliminating the attack vector.
CRITICAL 9.8 · 2026-05-18 · PHP
verbb/formie · Pattern: UNSANITIZED_INPUT→TEMPLATE · 3x across ecosystem
Root cause : The application was parsing the 'defaultValue' of a hidden field as a Twig template even when the value was directly provided by the user. This allowed an attacker to inject malicious Twig template code into the 'defaultValue' which would then be executed by the server.
Impact : An unauthenticated attacker could achieve remote code execution on the server by injecting arbitrary Twig template code, leading to full system compromise.
Diff
--- a/src/fields/formfields/Hidden.php
+++ b/src/fields/formfields/Hidden.php
@@ -111,11 +111,9 @@ public function serializeValue(mixed $value, ?ElementInterface $element = null):
// Check if there's no value been added on the front-end, and use the default value
if ($value === '') {
$value = $this->defaultValue;
$value = Variables::getParsedValue($this->defaultValue, $element);
}
$value = Variables::getParsedValue($value, $element);
// Immediately update the value for the element, so integrations use the up-to-date value
if ($element) {</pre>
Fix : The patch modifies the logic to ensure that the 'defaultValue' is only parsed as a Twig template if the front-end value is empty. If a value is provided from the front-end, it is no longer passed through the template parser, preventing injection.
CRITICAL 9.8 · 2026-05-14 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause : The vm2 sandbox failed to properly sanitize values returned from async generator functions, specifically when an async generator's `yield*` delegates to an inner async iterator and a thenable's `.then` callback throws synchronously. V8's internal PromiseResolveThenableJob would capture this exception and deliver it to sandbox code as an iterator result, bypassing existing sanitization mechanisms for exceptions and promise rejections.
Impact : An attacker could escape the vm2 sandbox, allowing them to execute arbitrary code in the host environment with the privileges of the Node.js process running the sandbox.
Diff
--- a/lib/setup-sandbox.js
+++ b/lib/setup-sandbox.js
@@ -983,6 +983,381 @@ if (typeof bridge.setHostPromiseSanitizers === 'function') {
bridge.setHostPromiseSanitizers(e => handleException(from(e)), from);
}
+// SECURITY (GHSA-248r-7h7q-cr24): Async generator yield*-return thenable
+// exception capture. When sandbox code calls i.return(thenable) on an
+// async generator that delegates via yield* to an inner async iterator
+// without a return method, V8's PromiseResolveThenableJob captures any
+// synchronous throw from the thenable's .then callback and the yield*
+// machinery delivers it to sandbox code as an iterator result
+// ({ value: thrown, done: false }). This bypasses (a) the transformer's
+// catch-block instrumentation (the catch is implicit in V8 internals)
+// and (b) the globalPromise.prototype.then rejection sanitizer above,
+// because internal Await uses PerformPromiseThen directly and never
+// invokes the user-visible .then override. Wrap
+// %AsyncGeneratorPrototype%.next / .return / .throw so every value
+// flowing out of an async generator into sandbox code is routed through
+// handleException — restoring the invariant that no host-realm value
+// can reach sandbox code without sanitization.
+let localAsyncGeneratorPrototype = null;Fix : The patch wraps the `%AsyncGeneratorPrototype%.next`, `.return`, and `.throw` methods. This ensures that all values flowing out of an async generator into sandbox code are routed through `handleException` for sanitization. It also introduces robust handling for thenables passed to these methods, preventing various bypasses related to synchronous throws, nested thenables, and Time-of-Check to Time-of-Use (TOCTOU) attacks on `.then` getters.
CRITICAL 9.8 · 2026-05-14 · C#
Marten · Pattern: UNSANITIZED_INPUT→SQL · 15x across ecosystem
Root cause : The application directly interpolated the 'regConfig' parameter into a SQL query without proper validation or sanitization. This allowed an attacker to inject arbitrary SQL commands by manipulating the 'regConfig' value.
Impact : An attacker could execute arbitrary SQL commands on the PostgreSQL database, potentially leading to data exfiltration, modification, or deletion, and even remote code execution depending on database privileges.
Diff
--- a/src/Marten/Linq/SqlGeneration/Filters/FullTextWhereFragment.cs
+++ b/src/Marten/Linq/SqlGeneration/Filters/FullTextWhereFragment.cs
@@ -18,6 +31,8 @@ internal class FullTextWhereFragment: ISqlFragment
public FullTextWhereFragment(DocumentMapping? mapping, FullTextSearchFunction searchFunction, string searchTerm,
string regConfig = FullTextIndexDefinition.DefaultRegConfig)
{
+ ValidateRegConfig(regConfig);
+
_regConfig = regConfig;
_dataConfig = GetDataConfig(mapping, regConfig).Replace("data", "d.data");</pre>
Fix : The patch introduces a regular expression to validate the 'regConfig' parameter. It ensures that 'regConfig' only contains characters valid for a PostgreSQL text-search configuration name, rejecting any input that could lead to SQL injection.
CRITICAL 9.8 · 2026-05-08 · PHP
snipe/snipe-it · Pattern: MISSING_AUTHZ→RESOURCE · 55x across ecosystem
Root cause : The application allowed users with 'view' permissions on an object to upload files associated with that object. This is a weaker permission than 'update', which should be required for file uploads, leading to an authorization bypass for file modification.
Impact : An attacker with only 'view' permissions on an object could upload arbitrary files, potentially leading to remote code execution if the uploaded file is a malicious script (e.g., PHP file) and the server is configured to execute it.
Diff
- $this->authorize('view', $object);
+ $this->authorize('update', $object);Fix : The patch changes the authorization check for file uploads from 'view' to 'update'. This ensures that only users with sufficient privileges to modify an object can upload files associated with it.
CRITICAL 9.8 · 2026-04-24 · JavaScript
electerm · Pattern: UNSANITIZED_INPUT→COMMAND · 39x across ecosystem
Root cause : The original `runLinux` function used `exec` from `shelljs` to execute shell commands, constructing parts of the command string directly from unsanitized version information (`ver`) and folder names (`folderName`). An attacker could manipulate these inputs to inject arbitrary shell commands.
Impact : An attacker could achieve arbitrary code execution on the system where the `electerm` package is being installed, potentially leading to full system compromise.
Diff
--- a/npm/install.js
+++ b/npm/install.js
@@ -100,9 +100,27 @@
}
async function runLinux (folderName, filePattern) {
const ver = await getVer()
const target = resolve(__dirname, ../electerm-${ver.replace('v', '')}-${folderName})
const targetNew = resolve(__dirname, '../electerm')
exec(`rm -rfFix : The patch introduces `sanitizeVersion` and `sanitizeFilename` functions to validate and clean inputs before they are used in shell commands. It also replaces `exec` with `execSync` for synchronous execution and `execFile` for safer execution of specific binaries, avoiding direct shell command construction with untrusted input.
CRITICAL 9.8 · 2026-04-24 · Go
github.com/woven-planet/go-zserio · Pattern: DOS→RESOURCE_EXHAUSTION · 52x across ecosystem
Root cause : The application did not limit the size of arrays, byte buffers, or strings when deserializing data from a zserio bitstream. An attacker could provide a crafted input with an extremely large declared size, causing the application to attempt to allocate an unbounded amount of memory.
Impact : An attacker could trigger a denial of service by causing the application to exhaust available memory, leading to crashes or system instability.
Diff
--- a/ztype/array_decode.go
+++ b/ztype/array_decode.go
arraySize := array.FixedSize
// Limit the initial capacity to a reasonable number to avoid excessive memory allocation.
// This is needed in case the input is untrusted could have an overly large value.
array.RawArray = make([]T, 0, arraySize)
if maxInitialArrayCapacityInt == 0 {
array.RawArray = make([]T, 0, arraySize)
} else {
array.RawArray = make([]T, 0, min(arraySize, maxInitialArrayCapacityInt))
}Fix : The patch introduces maximum initial capacity limits for arrays, byte buffers, and strings during deserialization. These limits are configurable via environment variables (ZSERIO_MAX_INITIAL_ARRAY_SIZE, ZSERIO_MAX_INITIAL_BLOB_SIZE, ZSERIO_MAX_INITIAL_STRING_SIZE) and prevent excessive memory allocation based on untrusted input.
CRITICAL 9.8 · 2026-04-17 · Python
praisonai · Pattern: UNSANITIZED_INPUT→COMMAND · 39x across ecosystem
Root cause : The code did not validate the executable part of the command input.
Impact : An attacker could execute arbitrary commands on the server if they could control the `--mcp` argument.
Diff
Before:
cmd = parts[0]
After:
basename = os.path.basename(cmd)
if basename not in ALLOWED_MCP_COMMANDS:
raise ValueError(...)Fix : The patch adds a whitelist of allowed MCP command executables and raises an error if the provided command is not in this list.
CRITICAL 9.8 · 2026-04-16 · Python
uefi-firmware · Pattern: BUFFER_OVERFLOW→STACK · 2x across ecosystem
Root cause : The `MakeTable` function, responsible for creating Huffman code mapping tables, did not adequately validate the `BitLen` array values. Specifically, it failed to check if `BitLen[Index]` exceeded 16 or if `Start[Len]` (calculated from `BitLen`) could lead to an out-of-bounds write when indexing the `Table` array, which is allocated on the stack.
Impact : An attacker providing specially crafted compressed data could cause a stack out-of-bounds write, potentially leading to arbitrary code execution or denial of service by corrupting stack data or control flow.
Diff
--- a/uefi_firmware/compression/Tiano/Decompress.c
+++ b/uefi_firmware/compression/Tiano/Decompress.c
@@ -208,14 +188,16 @@ Routine Description:
}
for (Index = 0; Index < NumOfChar; Index++) {
if (BitLen[Index] > 16) {
return (UINT16) BAD_TABLE;
}
Count[BitLen[Index]]++;
}
@@ -245,18 +227,20 @@ Routine Description:
if (Len <= TableBits) {
if (Start[Len] >= NextCode || NextCode > MaxTableLength) {
return (UINT16) BAD_TABLE;
}
for (Index = Start[Len]; Index < NextCode; Index++) {
if(Index >= TableSize)
{
Sd->mBadAlgorithm = 1;
return (UINT16) BAD_TABLE;
}
Table[Index] = Char;
}
+Fix : The patch adds checks within the `MakeTable` function to ensure that `BitLen[Index]` does not exceed 16 and that calculated table indices (`Start[Len]`) do not go out of bounds of the `Table` array. It also removes the `mBadAlgorithm` flag and replaces it with a direct return of `BAD_TABLE` upon detection of an invalid table.
CRITICAL 9.8 · 2026-04-16 · C#
Microsoft.Native.Quic.MsQuic.OpenSSL · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause : The code did not properly validate the count value before using it, allowing an attacker to potentially elevate privileges.
Impact : An attacker could exploit this vulnerability to perform actions that require higher privileges than intended.
Diff
Before:
Largest -= (Block.Gap + 1);
Count = Block.AckBlock + 1;
After:
if (Count > Largest + 1) {
*InvalidFrame = TRUE;
return FALSE;
}
Largest -= (Block.Gap + 1);
Count = Block.AckBlock + 1;Fix : The patch adds a validation check to ensure that Count is within a safe range before proceeding with further operations, preventing potential privilege escalation.
CRITICAL 9.8 · 2026-04-16 · Python
uefi-firmware · Pattern: BUFFER_OVERFLOW→HEAP · 20x across ecosystem
Root cause : The vulnerability existed in the `MakeTable` function within the Tiano decompressor. Specifically, the `Table` array, which is used to store Huffman code mappings, could be written to beyond its allocated bounds if the calculated `Index` or `NextCode` values exceeded the expected `TableSize` (or `MaxTableLength`). This was due to insufficient bounds checking on the `Index` variable before writing to `Table[Index]`, particularly when `Len` was less than or equal to `TableBits`.
Impact : An attacker could craft a malicious compressed UEFI firmware image that, when processed by the decompressor, would trigger a heap out-of-bounds write. This could lead to denial of service (crash), arbitrary code execution, or other memory corruption issues, compromising the integrity and security of the system's firmware.
Diff
--- a/uefi_firmware/compression/Tiano/Decompress.c
+++ b/uefi_firmware/compression/Tiano/Decompress.c
@@ -208,14 +188,16 @@ Routine Description:
}
for (Index = 0; Index < NumOfChar; Index++) {
if (BitLen[Index] > 16) {
return (UINT16) BAD_TABLE;
}
Count[BitLen[Index]]++;
}
// ... (lines omitted for brevity)
if (Len <= TableBits) {
if (Start[Len] >= NextCode || NextCode > MaxTableLength) {
return (UINT16) BAD_TABLE;
}
for (Index = Start[Len]; Index < NextCode; Index++) {
if(Index >= TableSize)
{
Sd->mBadAlgorithm = 1;
return (UINT16) BAD_TABLE;
}
Table[Index] = Char;
}
} else {Fix : The patch introduces explicit bounds checks within the `MakeTable` function. It now verifies that `BitLen[Index]` does not exceed 16 and that `Start[Len]` and `NextCode` remain within the `MaxTableLength` before writing to the `Table` array. Additionally, it removes the `mBadAlgorithm` flag and simplifies the `TableSize` calculation, ensuring that all writes to `Table` are within its allocated memory.
CRITICAL 9.8 · 2026-04-15 · Python
upsonic · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause : The code snippet provided does not contain any obvious security vulnerabilities.
Impact : No impact can be determined from the given code snippet.
Fix : No fix is applicable as there are no known issues in the provided code.
CRITICAL 9.8 · 2026-04-06 · Python
changedetection.io · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : The `login_optionally_required` decorator was moved above the route decorators, allowing unauthenticated access to routes that should be protected.
Impact : An attacker could bypass authentication and perform actions they are not authorized to do, such as downloading backups or removing backup files.
Diff
Before:
- @login_optionally_required
@backups_blueprint.route("/request-backup", methods=['GET'])
After:
+ @backups_blueprint.route("/request-backup", methods=['GET'])
+ @login_optionally_requiredFix : Moved the `login_optionally_required` decorator below all route decorators to ensure proper authentication checks.
CRITICAL 9.6 · 2026-06-04 · PHP
WWBN/AVideo · Pattern: UNSANITIZED_INPUT→XSS · 51x across ecosystem
Root cause : The application was vulnerable to XSS because it directly used user-supplied input from 'webSocketSelfURI' and 'page_title' parameters in the client-side DOM without proper sanitization or validation. An attacker could inject malicious JavaScript through these parameters.
Impact : An unauthenticated attacker could inject arbitrary JavaScript code into other users' browsers, leading to session hijacking, defacement, data theft, or redirection to malicious sites.
Diff
--- a/plugin/YPTSocket/MessageSQLiteV2.php
+++ b/plugin/YPTSocket/MessageSQLiteV2.php
@@ -89,12 +89,18 @@ public function onOpen(ConnectionInterface $conn)
$client['yptDeviceId'] = $json->yptDeviceId;
$client['client'] = deviceIdToObject($json->yptDeviceId);
if (!empty($wsocketGetVars['webSocketSelfURI'])) {
- $client['selfURI'] = $wsocketGetVars['webSocketSelfURI'];
+ $rawURI = $wsocketGetVars['webSocketSelfURI'];
+ // Only accept http/https URIs to prevent javascript: href injection
+ if (filter_var($rawURI, FILTER_VALIDATE_URL) && preg_match('/^https?:\/\//i', $rawURI)) {
+ $client['selfURI'] = $rawURI;
+ } else {
+ $client['selfURI'] = $json->selfURI;
+ }
} else {
$client['selfURI'] = $json->selfURI;
}
$client['isCommandLine'] = @$wsocketGetVars['isCommandLine'];
- $client['page_title'] = @utf8_encode(@$wsocketGetVars['page_title']);
+ $client['page_title'] = htmlspecialchars((string)@$wsocketGetVars['page_title'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
$client['ip'] = $json->ip;
if (!empty($json->location)) {Fix : The patch addresses the vulnerability by sanitizing the 'page_title' parameter using htmlspecialchars to prevent script injection. It also validates the 'webSocketSelfURI' parameter to ensure it is a valid HTTP/HTTPS URL, preventing 'javascript:' scheme injection.
CRITICAL 9.6 · 2026-04-23 · Ruby
openc3 · Pattern: UNSANITIZED_INPUT→SQL · 15x across ecosystem
Root cause : The application directly embedded user-controlled input (start_time, end_time, col_name) into SQL queries without proper sanitization or parameterization. This allowed an attacker to inject arbitrary SQL code by crafting malicious input values.
Impact : An attacker could execute arbitrary SQL commands on the QuestDB time-series database, potentially leading to data exfiltration, modification, or deletion, and could even achieve remote code execution in some database configurations.
Diff
Before:
query += "WHERE T0.PACKET_TIMESECONDS < '#{start_time}' LIMIT -1"
result = @@conn.exec(query)
After:
query += "WHERE T0.PACKET_TIMESECONDS < $1 LIMIT -1"
query_params << start_time
result = @@conn.exec_params(query, query_params)Fix : The patch modifies the `tsdb_lookup` and `create_table` methods in both Ruby and Python implementations to use parameterized queries. Instead of directly interpolating user input into the SQL string, placeholders ($1, $2 or %s) are used, and the values are passed as separate parameters to the database driver's `exec_params` or `execute` method.
CRITICAL 9.6 · 2026-04-22 · RUST
nimiq-block · Pattern: INTEGER_OVERFLOW→BOUNDARY · 7x across ecosystem
Root cause : The vulnerability stemmed from improper validation of `BitSet` indices representing validator slots. An attacker could craft a `BitSet` with out-of-range indices or indices that, when truncated to `u16`, would map to valid slots. This allowed them to bypass the quorum check for skip blocks and equivocation proofs by making it appear as if enough validators had signed, even if they hadn't.
Impact : An attacker could forge valid skip blocks or equivocation proofs without the required supermajority of validator signatures. This could lead to a denial of service, allowing them to halt or disrupt the blockchain's consensus mechanism.
Diff
--- a/primitives/block/src/multisig.rs
+++ b/primitives/block/src/multisig.rs
@@ -37,3 +37,14 @@ impl MultiSignature {
}
}
}
+
+pub(crate) fn checked_signer_slots(signers: &BitSet) -> Option<Vec<u16>> {
+ let mut slots = Vec::with_capacity(signers.len());
+ for slot in signers.iter() {
+ if slot >= Policy::SLOTS as usize || slot > u16::MAX as usize {
+ return None;
+ }
+ slots.push(slotFix : The patch introduces a new `checked_signer_slots` function that rigorously validates `BitSet` indices. It ensures that all signer slots are within the allowed range (`Policy::SLOTS`) and do not exceed `u16::MAX` before processing them. This prevents out-of-range or truncated indices from being used to bypass quorum checks.
CRITICAL 9.6 · 2026-04-10 · Python
lollms · Pattern: UNSANITIZED_INPUT→XSS · 51x across ecosystem
Root cause : The application did not properly sanitize user-supplied content before storing it in the database and later rendering it. This allowed attackers to inject malicious scripts into posts, comments, and direct messages.
Impact : An attacker could inject arbitrary client-side scripts, leading to session hijacking, defacement, redirection to malicious sites, or other client-side attacks against users viewing the compromised content.
Diff
--- a/backend/routers/social/__init__.py
+++ b/backend/routers/social/__init__.py
@@ -149,9 +176,12 @@ def create_post(
moderation_enabled = settings.get("ai_bot_moderation_enabled", False)
initial_status = "pending" if moderation_enabled else "validated"
Sanitize content to prevent Stored XSS
clean_content = sanitize_content(post_data.content)
new_post = DBPost(
author_id=current_user.id,
content=post_data.content,
content=clean_content,
visibility=post_data.visibility,</pre>
Fix : The patch introduces a `sanitize_content` function using the `bleach` library to clean user input. This function is applied to all user-generated content (posts, comments, direct messages, and group conversation names) before it is stored in the database, stripping or escaping disallowed HTML tags and attributes.
CRITICAL 9.4 · 2026-05-05 · PHP
getgrav/grav · Pattern: PRIVILEGE_ESCALATION→ROLE · 20x across ecosystem
Root cause : The Grav user registration process lacked server-side validation for critical privilege-related fields like 'groups' and 'access'. This allowed an attacker to include these fields in their registration form submission, and the application would honor these values, effectively granting them elevated privileges.
Impact : An attacker could register a new user account and assign themselves administrative or other high-privilege roles, leading to full control over the Grav instance.
Diff
--- a/login.php
+++ b/login.php
@@ -1040,6 +1047,17 @@ private function processUserRegistration(FormInterface $form, Event $event): voi
}
}
if (in_array($field, $privilegeFields, true)) {
if ($form_data->get($field) !== null) {
$this->grav['log']->warning(sprintf(
'Login registration: ignored client-supplied "%s" from form submission (username=%s)',
$field,
is_string($username) ? $username : '<invalid>'
));
}
continue;
}
if (!isset($data[$field]) && $form_data->get($field)) {
$data[$field] = $form_data->get($field);
}</pre>
Fix : The patch explicitly identifies 'groups' and 'access' as privilege fields and prevents them from being sourced directly from public registration form input. Any client-supplied values for these fields are now ignored, and a warning is logged.
CRITICAL 9.4 · 2026-05-04 · PHP
nabeel/phpvms · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : The vulnerability existed because the /importer endpoint, which is responsible for importing data and can wipe the existing database, lacked proper authorization checks. This allowed any unauthenticated user to access and trigger the database wipe functionality.
Impact : An attacker could completely wipe the entire database of the phpVMS installation, leading to a denial of service and significant data loss for the application owner.
Diff
--- resources/views/system/importer/app.blade.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
--- resources/views/system/importer/step1-configure.blade.php
+++ /dev/null
@@ -1,132 +0,0 @@
-@extends('system.importer.app')Fix : The patch completely removes the vulnerable /importer functionality by deleting all associated view files. This eliminates the unauthorized access point and prevents the database wipe from being triggered by unauthenticated users.
CRITICAL 9.4 · 2026-04-14 · Python
excel-mcp-server · Pattern: PATH_TRAVERSAL→FILE_READ · 37x across ecosystem
Root cause : The code did not properly sanitize the input filename, allowing attackers to traverse directories and access files outside of the intended directory.
Impact : An attacker could read or write arbitrary files on the server, potentially leading to data theft, unauthorized modifications, or other malicious activities.
Diff
Before:
return os.path.join(EXCEL_FILES_PATH, filename)
After:
base = os.path.realpath(EXCEL_FILES_PATH)
candidate = os.path.realpath(os.path.join(base, filename))
if not _resolved_path_is_within(base, candidate):
raise ValueError(f"Invalid filename: {filename}, path escapes EXCEL_FILES_PATH")Fix : The patch introduced a function `_resolved_path_is_within` to ensure that the resolved path is within the allowed directory. It also added checks to validate the filename and prevent absolute paths when not in SSE mode.
CRITICAL 9.4 · 2026-04-08 · JavaScript
@delmaredigital/payload-puck · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : The endpoints were missing proper authorization checks, allowing unauthenticated access to CRUD operations on Puck-registered collections.
Impact : An attacker could perform any CRUD operation on the collections without authentication, potentially leading to data leakage or manipulation.
Diff
Before:
- const body = await req.json?.()
- const { _locale } = body || {}
- const locale = resolveLocale(req, _locale)
After:
const locale = resolveLocale(req)
const result = await req.payload.find({
collection: collection as CollectionSlug,
req,
overrideAccess: false,</pre>
Fix : The patch adds access control by passing `overrideAccess: false` and `req` to Payload's local API, ensuring that collection-level access rules are enforced.
CRITICAL 9.1 · 2026-06-10 · Go
github.com/dhax/go-base · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 9.1 · 2026-05-07 · Go
github.com/gtsteffaniak/filebrowser · Pattern: PATH_TRAVERSAL→FILE_DELETE · 5x across ecosystem
Root cause : The application did not properly sanitize user-supplied paths in the DELETE API for public shares. An attacker could provide a path containing '..' sequences, which would allow them to traverse outside the intended directory and delete arbitrary files on the server.
Impact : An unauthenticated attacker could delete any file on the server that the FileBrowser process has write permissions to, potentially leading to denial of service or data loss.
Diff
--- a/backend/http/middleware.go
+++ b/backend/http/middleware.go
@@ -53,7 +53,11 @@ type handleFunc func(w http.ResponseWriter, r *http.Request, data *requestContex
func withHashFileHelper(fn handleFunc) handleFunc {
return withOrWithoutUserHelper(func(w http.ResponseWriter, r *http.Request, data *requestContext) (int, error) {
hash := r.URL.Query().Get("hash")
- path := r.URL.Query().Get("path")
+ inputPath := r.URL.Query().Get("path")
+ path, err := utils.SanitizeUserPath(inputPath)
+ if err != nil && inputPath != "" {
+ return http.StatusBadRequest, err
+ }
// Get the file link by hash
link, err := store.Share.GetByHash(hash)</pre>
Fix : The patch introduces a `utils.SanitizeUserPath` function to validate and sanitize user-provided paths, specifically in the `withHashFileHelper` and `resourceBulkDeleteHandler` functions. This prevents path traversal sequences like '..' from being interpreted by the file system.
CRITICAL 9.1 · 2026-05-05 · PHP
getgrav/grav · Pattern: PATH_TRAVERSAL→FILE_WRITE · 25x across ecosystem
Root cause : The vulnerability stemmed from multiple issues. Firstly, the `unZip` function did not validate archive entry names, allowing 'Zip Slip' attacks where malicious ZIP files could write files outside the intended directory using path traversal sequences (e.g., `../`). Secondly, the `attribute` function in `MediaObjectTrait` allowed arbitrary attribute names, which could be exploited for XSS by injecting event handlers (e.g., `onerror`) or other dangerous attributes. Lastly, the `detectXss` function's regex for `on_events` was bypassable, and the SVG parsing in `VectorImageMedium` was vulnerable to XXE attacks due to not stripping DOCTYPE/ENTITY declarations and lacking `LIBXML_NONET`.
Impact : An attacker could achieve remote code execution by uploading a crafted plugin ZIP file that writes PHP files to arbitrary locations. They could also inject malicious JavaScript via XSS in image attributes or potentially perform server-side request forgery (SSRF) or information disclosure via XXE in SVG files.
Diff
--- a/system/src/Grav/Common/GPM/Installer.php
+++ b/system/src/Grav/Common/GPM/Installer.php
@@ -179,6 +179,24 @@ public static function unZip($zip_file, $destination)
$archive = $zip->open($zip_file);
if ($archive === true) {
$numFiles = $zip->numFiles;
for ($i = 0; $i < $numFiles; $i++) {
$entryName = (string) $zip->getNameIndex($i);
if (!self::isSafeArchiveEntry($entryName)) {
self::$error = self::ZIP_EXTRACT_ERROR;
$zip->close();
return false;
}
}
Folder::create($destination);
$unzip = $zip->extractTo($destination);</pre>
Fix : The patch introduces `isSafeArchiveEntry` to validate ZIP entry names, preventing path traversal. It also adds `isSafeAttributeName` to restrict allowed HTML attribute names, mitigating XSS. The `detectXss` regex for `on_events` was improved to be more robust. Finally, the SVG parsing now strips DOCTYPE/ENTITY declarations and uses `LIBXML_NONET` to prevent XXE vulnerabilities.
CRITICAL 9.1 · 2026-05-04 · Java
org.openmrs.api:openmrs-api · Pattern: UNSANITIZED_INPUT→TEMPLATE · 3x across ecosystem
Root cause : The application used Apache Velocity for evaluating user-supplied criteria in `ConceptReferenceRangeUtility.java`. The `evaluateCriteria` method directly passed unsanitized user input into `velocityEngine.evaluate()`, allowing an attacker to inject Velocity Template Language (VTL) directives. Since Velocity templates can execute arbitrary Java code, this led to Remote Code Execution (RCE).
Impact : An authenticated attacker with privileges to create or modify ConceptReferenceRange objects could store malicious Velocity templates. When these templates were evaluated, the attacker could achieve arbitrary code execution on the server, leading to full system compromise.
Diff
--- a/api/src/main/java/org/openmrs/util/ConceptReferenceRangeUtility.java
+++ b/api/src/main/java/org/openmrs/util/ConceptReferenceRangeUtility.java
@@ -96,387 +128,383 @@ public boolean evaluateCriteria(String criteria, ConceptReferenceRangeContext co
throw new IllegalArgumentException("Failed to evaluate criteria with reason: criteria is empty");
}
VelocityContext velocityContext = new VelocityContext();
velocityContext.put("fn", this);
velocityContext.put("patient", HibernateUtil.getRealObjectFromProxy(context.getPerson()));
velocityContext.put("context", context);
velocityContext.put("obs", context.getObs());
velocityContext.put("encounter", context.getEncounter());
velocityContext.put("date", context.getDate());
VelocityEngine velocityEngine = new VelocityEngine();
try {
Properties props = new Properties();
props.put("runtime.log.logsystem.log4j.category", "velocity");
props.put("runtime.log.logsystem.log4j.logger", "velocity");
velocityEngine.init(props);
} catch (Exception e) {
throw new APIException("Failed to create the velocity engine: " + e.getMessage(), e);
}
StringWriter writer = new StringWriter();
String wrappedCriteria = "#set( $criteria = " + criteria + " )$criteria";
Map<String, Object> root = new HashMap<>();
root.put("$fn", functions);
root.put("$patient", HibernateUtil.getRealObjectFromProxy(context.getPerson()));
root.put("$context", context);
root.put("$obs", context.getObs());
root.put("$encounter", context.getEncounter());
root.put("$date", context.getDate());
try {
velocityEngine.evaluate(velocityContext, writer, ConceptReferenceRangeUtility.class.getName(), wrappedCriteria);
return Boolean.parseBoolean(writer.toString());
} catch (ParseErrorException e) {
throw new APIException("An error occurred while evaluating criteria. Invalid criteria: " + criteria, e);
Expression expression = EXPRESSION_CACHE.get(criteria, PARSER::parseExpression);
Boolean result = expression.getValue(EVAL_CONTEXT, root, Boolean.class);
return result != null && result;
} catch (SpelEvaluationException e) {
SpelMessage msg = e.getMessageCode();
if (msg == SpelMessage.METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED
|| msg == SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL) {
return false;
}
throw new APIException("An error occurred while evaluating criteria: " + criteria, e);
} catch (Exception e) {
throw new APIException("An error occurred while evaluating criteria: ", e);
throw new APIException("An error occurred while evaluating criteria: " + criteria, e);
}
}Fix : The patch replaces the vulnerable Apache Velocity template engine with Spring Expression Language (SpEL). It also introduces a `CriteriaFunctions` class to explicitly define available functions, preventing direct access to arbitrary Java methods. Additionally, a cache for parsed expressions is implemented to improve performance.
CRITICAL 9.1 · 2026-04-30 · Go
github.com/go-pkgz/auth/v2 · Pattern: PRIVILEGE_ESCALATION→ROLE · 20x across ecosystem
Root cause : The vulnerability existed because the Patreon OAuth2 provider incorrectly generated the local user ID. Instead of using the unique ID provided by Patreon (uinfoJSON.Data.ID), it used an uninitialized or default value from userInfo.ID, which was likely constant or empty across all users. This resulted in all authenticated Patreon users being assigned the same local user ID.
Impact : An attacker could impersonate any other Patreon-authenticated user by simply logging in with their own Patreon account. This allows for cross-user impersonation and unauthorized access to other users' data or actions within the application.
Diff
- userInfo.ID = "patreon_" + token.HashID(sha1.New(), userInfo.ID)
+ userInfo.ID = "patreon_" + token.HashID(sha1.New(), uinfoJSON.Data.ID)Fix : The patch corrects the user ID generation logic for the Patreon OAuth2 provider. It changes the source of the ID used for hashing from the potentially uninitialized `userInfo.ID` to the unique and correct `uinfoJSON.Data.ID` obtained from the Patreon user information JSON response. This ensures each Patreon user gets a unique local ID.
CRITICAL 9.1 · 2026-04-30 · Python
sentry · Pattern: MISSING_AUTH→ENDPOINT · 28x across ecosystem
Root cause : During the SAML SSO setup process, Sentry was using the email provided by the Identity Provider (IdP) to link the SAML identity to a Sentry user. This allowed a malicious IdP or an attacker controlling the IdP's response to assert an arbitrary email address, potentially linking the SAML identity to an existing Sentry user who was not the administrator performing the setup.
Impact : An attacker could link their SAML identity to an arbitrary Sentry user's account, effectively taking over that user's account within the organization. This could lead to unauthorized access to sensitive data and actions.
Diff
--- a/src/sentry/auth/helper.py
+++ b/src/sentry/auth/helper.py
@@ -1017,7 +1017,11 @@ def _finish_setup_pipeline(self, identity: Mapping[str, Any]) -> HttpResponseRed
organization_id=self.organization.id, provider=self.provider.key, config=config
)
self.auth_handler(identity).handle_attach_identity(om)
# The setup flow should always link the identity to the admin who is
# performing setup, so override the email to ensure resolve_email_to_user
# returns the authenticated user rather than whoever the IdP asserted.
setup_identity = {**identity, "email": request.user.email}
self.auth_handler(setup_identity).handle_attach_identity(om)
auth.mark_sso_complete(request, self.organization.id)</pre>
Fix : The patch ensures that during the SAML SSO setup flow, the identity is always linked to the email of the administrator who is currently logged in and performing the setup. It explicitly overrides the email from the IdP's response with the authenticated user's email before attaching the identity.
CRITICAL 9.1 · 2026-04-10 · Python
gramps-webapi · Pattern: PATH_TRAVERSAL→FILE_WRITE · 25x across ecosystem
Root cause : The application extracted files from a user-provided zip archive without validating the paths of the entries within the archive. This allowed an attacker to craft a zip file containing entries with malicious paths (e.g., `../../../../etc/passwd`) that, when extracted, would write files outside the intended temporary directory.
Impact : An attacker could write arbitrary files to arbitrary locations on the server's filesystem, potentially leading to remote code execution, data corruption, or denial of service.
Diff
temp_dir_real = os.path.realpath(temp_dir)
for member in zip_file.namelist():
member_path = os.path.realpath(os.path.join(temp_dir_real, member))
if not member_path.startswith(temp_dir_real + os.sep):
raise ValueError(f"Zip Slip path traversal detected: {member}")Fix : The patch adds a validation step before extraction. It iterates through each member of the zip file, constructs its intended extraction path, and checks if the real path of the member remains within the designated temporary directory. If a path traversal attempt is detected, an error is raised.
CRITICAL 9.0 · 2026-05-05 · Java
com.arcadedb:arcadedb-server · Pattern: MISSING_AUTHZ→RESOURCE · 55x across ecosystem
Root cause : The ArcadeDB server did not properly enforce security configurations for newly created databases and had a flawed logic for merging database-specific and wildcard security group configurations. This allowed users to create databases without proper security settings and bypass intended authorization rules by exploiting how group permissions were retrieved.
Impact : An attacker could create new databases that are unsecured by default, gaining unauthorized access to them. They could also potentially bypass authorization checks on existing databases by manipulating schema properties or exploiting the flawed group configuration merge logic, leading to data access or modification across databases.
Diff
--- a/server/src/main/java/com/arcadedb/server/ArcadeDBServer.java
+++ b/server/src/main/java/com/arcadedb/server/ArcadeDBServer.java
@@ -474,6 +474,8 @@ public ServerDatabase createDatabase(final String databaseName, final ComponentF
configuration.getValueAsString(GlobalConfiguration.SERVER_DATABASE_DIRECTORY) + File.separator
+ databaseName).setAutoTransaction(true);
factory.setSecurity(getSecurity());
if (factory.exists())
throw new IllegalArgumentException("Database '" + databaseName + "' already exists");</pre>
Fix : The patch ensures that newly created databases inherit the server's security configuration. It also refines the logic for retrieving database group configurations, specifically for wildcard ('*') entries, to correctly merge or return specific database groups, preventing unintended authorization bypasses.
CRITICAL 0.0 · 2026-06-10 · JavaScript
@whiskeysockets/baileys · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 0.0 · 2026-06-09 · Erlang
phoenix_storybook · Pattern: UNCLASSIFIED · 121x across ecosystem
Root cause :
Impact :
Fix :
CRITICAL 0.0 · 2026-06-04 · Python
stata-mcp · Pattern: UNSANITIZED_INPUT→COMMAND · 39x across ecosystem
Root cause : The application allowed an attacker to control the `log_file_name` parameter, which was directly used to construct a log file path. This lack of input validation enabled both path traversal characters (e.g., `../`) and potentially command injection through crafted filenames, as the log file name could influence commands executed by Stata.
Impact : An attacker could write arbitrary files to arbitrary locations on the file system, potentially leading to remote code execution by overwriting critical system files or injecting malicious scripts. They could also create log files with names that, when processed by Stata, could execute arbitrary commands.
Diff
--- a/src/stata_mcp/stata/stata_do/do.py
+++ b/src/stata_mcp/stata/stata_do/do.py
@@ -79,7 +82,8 @@ def execute_dofile(
"""
nowtime = get_nowtime()
log_name = log_file_name or nowtime
- log_file = self.log_file_path / f"{log_name}.log"
+ self._validate_log_name(log_name)
+ log_file = self.generate_log_file(log_name)Fix : The patch introduces a regular expression to validate the `log_file_name` parameter, ensuring it only contains alphanumeric characters, underscores, dots, or hyphens, and has a length between 1 and 128 characters. It also explicitly checks for path traversal attempts by disallowing parts like '.', '..', or empty strings in the path components.
CRITICAL 0.0 · 2026-05-26 · Java
org.xwiki.platform:xwiki-platform-rest-server · Pattern: MISSING_AUTHZ→RESOURCE · 55x across ecosystem
Root cause : The REST endpoint for importing XAR (XWiki Archive) files into a wiki did not perform any authorization checks. This allowed any unauthenticated or unauthorized user to upload and import a malicious XAR file.
Impact : An attacker could import arbitrary XAR files, potentially leading to remote code execution, privilege escalation, or complete compromise of the XWiki instance.
Diff
--- a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/wikis/WikiResourceImpl.java
+++ b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/wikis/WikiResourceImpl.java
@@ -74,6 +80,13 @@ public Wiki get(String wikiName) throws XWikiRestException
public Wiki importXAR(String wikiName, Boolean backup, String historyStrategy, InputStream is)
throws XWikiRestException
{
+ // Importing a XAR require wiki admin right
+ try {
+ this.authorizationManager.checkAccess(Right.ADMIN, new WikiReference(wikiName));
+ } catch (AccessDeniedException e) {
+ throw new WebApplicationException(e.getMessage(), Response.Status.FORBIDDEN);
+ }
+
try {
if (!this.wikis.exists(wikiName)) {
throw new WebApplicationException(Response.Status.NOT_FOUND);Fix : The patch adds an authorization check to the `importXAR` method. It now requires the user to have 'ADMIN' rights for the specified wiki before proceeding with the XAR import operation, throwing a 403 Forbidden error if the check fails.
CRITICAL 0.0 · 2026-05-26 · Java
org.xwiki.commons:xwiki-commons-classloader-api · Pattern: PATH_TRAVERSAL→FILE_READ · 37x across ecosystem
Root cause : The application used `Paths.get(fullPath).normalize()` to prevent path traversal. However, it did not correctly handle leading slashes in the `resourcePath` parameter. When a resource path started with one or more leading slashes (e.g., "//../"), `Paths.get().normalize()` would treat it differently than intended, allowing an attacker to bypass the `startsWith("../")` check and access resources outside the intended directory.
Impact : An attacker could use specially crafted `resources` parameters in `ssx` and `jsx` endpoints to read arbitrary files on the server's file system, potentially leading to information disclosure or further compromise.
Diff
--- a/xwiki-commons-core/xwiki-commons-classloader/xwiki-commons-classloader-api/src/main/java/org/xwiki/classloader/internal/ClassLoaderUtils.java
+++ b/xwiki-commons-core/xwiki-commons-classloader/xwiki-commons-classloader-api/src/main/java/org/xwiki/classloader/internal/ClassLoaderUtils.java
@@ -47,20 +47,30 @@ private static String resolveResourceName(String prefixPath, String resourcePath
fullPath = resourcePath;
// Prevent access to resources from other directories
// TODO: find or implement something closed to Servlet ClassLoader behavior to be as accurate as possible
// and be able to reuse the normalized result
Path normalizedResource = Paths.get(fullPath).normalize();
// On Tomcat, all leading / have no effect, contrary to Paths#normalize()
int index = 0;
while (index < fullPath.length() && fullPath.charAt(index) == '/') {
++index;
}
String normalizedPath = fullPath.substring(index);
Path normalizedResource = Paths.get(normalizedPath).normalize();
if (normalizedResource.startsWith("../")) {
throw new IllegalArgumentException(String.format(
"The provided resource name [%s] is trying to navigate out of the mandatory root location",
resourcePath));
fullPath));
}
} else {
fullPath = prefixPath + resourcePath;
// Prevent access to resources from other directories
// TODO: find or implement something closed to Servlet ClassLoader behavior to be as accurate as possible
// and be able to reuse the normalized result
// and be able to reuse the normalized result. Not so easy since the various applications servers can use
// different logics.
Path normalizedResource = Paths.get(fullPath).normalize();
if (!normalizedResource.startsWith(prefixPath)) {
throw new IllegalArgumentException(String.format(</pre>
Fix : The patch modifies the `resolveResourceName` method to explicitly remove all leading slashes from the `resourcePath` before normalization. This ensures that `Paths.get().normalize()` behaves consistently and the subsequent `startsWith("../")` check correctly identifies and prevents path traversal attempts.
CRITICAL 0.0 · 2026-05-12 · JavaScript
openclaude · Pattern: PRIVILEGE_ESCALATION→ROLE · 20x across ecosystem
Root cause : The `dangerouslyDisableSandbox` parameter in the BashTool was exposed to the AI model. Although the prompt attempted to guide the model on when to use it, the model could directly set this parameter in its tool calls, bypassing the intended user approval flow and security restrictions.
Impact : An attacker, via a malicious AI model, could execute arbitrary commands outside the sandbox environment, leading to potential remote code execution, data exfiltration, or system compromise on the host running the OpenClaude application.
Diff
--- a/src/tools/BashTool/BashTool.tsx
+++ b/src/tools/BashTool/BashTool.tsx
@@ -240,21 +240,28 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
run_in_background: semanticBoolean(z.boolean().optional()).describe(`Set to true to run this command in the background. Use Read to read the output later.`),
dangerouslyDisableSandbox: semanticBoolean(z.boolean().optional()).describe('Set this to true to dangerously override sandbox mode and run commands without sandboxing.'),
+ _dangerouslyDisableSandboxApproved: z.boolean().optional().describe('Internal: user-approved sandbox override'),
_simulatedSedEdit: z.object({
filePath: z.string(),
newContent: z.string()
}).optional().describe('Internal: pre-computed sed edit result from preview')
}));
-// Always omit _simulatedSedEdit from the model-facing schema. It is an internal-only
-// field set by SedEditPermissionRequest after the user approves a sed edit preview.
-// Exposing it in the schema would let the model bypass permission checks and the
-// sandbox by pairing an innocuous command with an arbitrary file write.
+// Always omit internal-only fields from the model-facing schema.
+// _simulatedSedEdit is set by SedEditPermissionRequest after the user approves a
+// sed edit preview; exposing it would let the model bypass permission checks and
+// the sandbox by pairing an innocuous command with an arbitrary file write.
+// dangerouslyDisableSandbox is also omitted because sandbox escape must be tied
+// to trusted user/internal provenance, not model-controlled tool input.
// Also conditionally remove run_in_background when background tasks are disabled.
const inputSchema = lazySchema(() => isBackgroundTasksDisabled ? fullInputSchema().omit({
run_in_background: true,
dangerouslyDisableSandbox: true,
_dangerouslyDisableSandboxApproved: true,
_simulatedSedEdit: true
}) : fullInputSchema().omit({
dangerouslyDisableSandbox: true,
_dangerouslyDisableSandboxApproved: true,
_simulatedSedEdit: true
}));Fix : The patch removes `dangerouslyDisableSandbox` from the model-facing schema of the BashTool and PowerShellTool. It introduces an internal-only `_dangerouslyDisableSandboxApproved` flag, which must be true for the sandbox to be disabled. This ensures that sandbox disabling can only be triggered by trusted internal logic, not directly by the AI model's input.
06:00 UTC Pull advisories (GitHub Advisory DB, GraphQL)
Filter: has linked patch commit, severity >= MEDIUM
↓
06:00:10 Fetch commit diff via GitHub API
Filter: exclude tests/docs/lockfiles, keep top 5 source files
↓
06:00:15 LLM analysis (Gemini 2.5 Flash)
Extract: vuln_type, root_cause, impact, fix_summary, key_diff
Map to closed taxonomy of 48 normalized pattern IDs
↓
06:00:20 Pattern matching against SQLite historical DB
Cross-language correlation, recurrence scoring
↓
06:00:25 Output: patches/*.md, README.md, docs/index.html
Single atomic commit per run
Three runs per day: 06:00, 14:00, 23:00 UTC. Render pipeline runs independently at 07:00, 15:00, 00:00 UTC.
Stack
| Component | Tech | Notes |
|---|---|---|
| Automation | GitHub Actions cron | Zero infra |
| Data source | GitHub Advisory DB | GraphQL, filtered on patch commits |
| LLM | Gemini 2.5 Flash | Free tier, JSON-only output |
| DB | SQLite rebuilt from JSONL | Git-friendly, versioned |
| Frontend | Static HTML | Client-side search, zero build step |
| Scripting | Python 3.11 | requests, jinja2, sqlite3 |
Stats
| Metric | Value |
|---|---|
| Total advisories | 706 |
| Unique patterns | 48 |
| Pending | 0 |
| Last updated | 2026-06-17 |
christbowel.com