Skip to content

Latest commit

 

History

1,967 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎣 Open Source Daily Catch

Automated Patch Intelligence for Security Engineers

Analysis Render Advisories Patterns

Live dashboard · How it works


GHSA-jrc7-96c5-q579

CRITICAL 10.0 · 2026-09-08 · JavaScript
maplibre-gl · Pattern: UNSANITIZED_INPUT→XSS · 108x across ecosystem

Root cause : The vulnerability existed because the `DOM.removeAttributes` method iterated directly over `elem.attributes`, which is a live `NamedNodeMap`. When a dangerous attribute was removed using `elem.removeAttribute(name)`, it modified the live collection, causing the loop to skip the next attribute in the original sequence, thus failing to sanitize all malicious attributes.

Impact : An attacker could bypass the HTML sanitizer, allowing them to inject malicious scripts or content into the DOM. This could lead to arbitrary code execution in the user's browser, session hijacking, or defacement of the web application.

Diff
--- a/src/util/dom.ts
+++ b/src/util/dom.ts
@@ -131,7 +131,7 @@ export class DOM {
 	 * @param elem - The element
 	 */
     private static removeAttributes(elem: Element) {
-        for (const {name, value} of elem.attributes) {
+        for (const {name, value} of Array.from(elem.attributes)) {
             if (!DOM.isPossiblyDangerous(name, value)) continue;
             elem.removeAttribute(name);
         }

Fix : The patch fixes the vulnerability by converting the live `NamedNodeMap` returned by `elem.attributes` into a static array using `Array.from()`. This ensures that all attributes are processed and sanitized, even when attributes are removed during the iteration, preventing the sanitizer bypass.

Advisory · Commit


GHSA-fph3-ghq9-vw66

CRITICAL 10.0 · 2026-09-03 · Go
github.com/siyuan-note/siyuan/kernel · Pattern: UNSANITIZED_INPUT→SQL · 32x across ecosystem

Root cause : The application directly concatenated user-supplied input into SQL queries and regular expressions without proper sanitization or parameterization. Specifically, the `fullTextSearchAssetContent` function, when `method` was set to 2 (SQL) or 3 (Regexp), allowed unauthenticated users to inject arbitrary SQL or regular expression syntax.

Impact : An unauthenticated attacker could execute arbitrary SQL commands on the underlying database, leading to data exfiltration, modification, or deletion. Additionally, they could perform REGEXP injection, potentially causing denial of service or information disclosure through crafted regular expressions.

Diff
--- a/kernel/model/asset_content.go
+++ b/kernel/model/asset_content.go
@@ -74,10 +75,12 @@ func GetAssetContent(id, query string, queryMethod int) (ret *AssetContent) {
table := "asset_contents_fts_case_insensitive"


filter := " id = '" + id + "'"


filter := "id = ?"
args := []any{id}
if "" != query {



  filter += " AND `" + table + "` MATCH '" + buildAssetContentColumnFilter() + ":(" + query + ")'"





  filter += " AND `" + table + "` MATCH ?"



  args = append(args, buildAssetContentColumnFilter()+":("+query+")")

}
projections := "id, name, ext, path, size, updated, " +




  highlight(" + table + ", 6, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS content"


stmt := "SELECT " + projections + " FROM " + table + " WHERE " + filter
assetContents := sql.SelectAssetContentsRawStmt(stmt, 1, 1)



  highlight(" + table + ", 6, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS content"


stmt := "SELECT " + projections + " FROM " + table + " WHERE " + filter
assetContents := sql.SelectAssetContentsRawStmtNoParseArgs(stmt, args, 1)

Fix : The patch refactors SQL query construction to use parameterized queries (prepared statements) via `?` placeholders and `sql.SelectAssetContentsRawStmtNoParseArgs` for all affected functions. It also modifies the regular expression search to use parameterized queries for the `REGEXP` operator, preventing direct concatenation of user input into the regex pattern.

Advisory · Commit


GHSA-q2vg-7qgx-x5fc

CRITICAL 10.0 · 2026-09-03 · Go
github.com/siyuan-note/siyuan/kernel · Pattern: UNSANITIZED_INPUT→SQL · 32x across ecosystem

Root cause : The application constructed SQL queries by directly concatenating user-controlled input (mentionKeywords and keyword) into the FTS MATCH clause without proper escaping. This allowed an attacker to inject arbitrary SQL into the query by crafting malicious input containing double quotes, breaking out of the intended string literal.

Impact : An attacker could execute arbitrary SQL commands within the database, potentially leading to data exfiltration, modification, or deletion, and could bypass intended access controls.

Diff
- buf.WriteString("\"" + mentionKeyword + "\"")
+ buf.WriteString(quoteFTSPhrase(mentionKeyword))
...
- sqlBlocks := sql.SelectBlocksRawStmtInBox(query, 1, Conf.Search.Limit, boxID)
+ sqlBlocks := sql.SelectBlocksRawStmtArgsInBox(query, args, Conf.Search.Limit, boxID)

Fix : The patch introduces a `quoteFTSPhrase` function to properly escape double quotes in user input for FTS queries. It also refactors the query construction to use parameterized queries via `sql.SelectBlocksRawStmtArgsInBox`, ensuring that user input is treated as data rather than executable code.

Advisory · Commit


GHSA-vh22-h7hf-www7

CRITICAL 10.0 · 2026-09-03 · Go
github.com/siyuan-note/siyuan/kernel · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-x2rj-828p-hx9m

CRITICAL 10.0 · 2026-08-21 · Python
xinference · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The application used the unsafe `eval()` function to parse tool-call arguments from untrusted model outputs. An attacker could craft a malicious string that, when evaluated by `eval()`, would execute arbitrary Python code on the server.

Impact : An attacker could achieve full remote code execution on the server hosting the Xinference application, leading to complete system compromise.

Diff
--- a/xinference/model/llm/utils.py
+++ b/xinference/model/llm/utils.py
-            data = eval(text, {}, {})
+            data = json.loads(text)
+        except (json.JSONDecodeError, TypeError):
+            try:
+                data = ast.literal_eval(text)

Fix : The patch replaces the unsafe `eval()` calls with a safer parsing mechanism. It first attempts to parse the input as JSON and, if that fails, falls back to `ast.literal_eval()`. `ast.literal_eval()` is a safe alternative to `eval()` for evaluating strings containing Python literal structures, preventing arbitrary code execution.

Advisory · Commit


GHSA-7pwq-q9jf-539h

CRITICAL 10.0 · 2026-08-18 · Ruby
kobako · Pattern: DESERIALIZATION→RCE · 25x across ecosystem

Root cause : The `kobako` gem allowed guest code to invoke arbitrary methods on host objects via `public_send`. This included Ruby's reflection and metaprogramming methods like `send`, `public_send`, `instance_eval`, `method`, `tap`, and `instance_variable_get`. An attacker could chain these methods to bypass the sandbox and execute arbitrary code on the host system.

Impact : An attacker could achieve Remote Code Execution (RCE) on the host system, completely escaping the intended sandbox environment. This allows full control over the host machine.

Diff
--- a/lib/kobako/transport/dispatcher.rb
+++ b/lib/kobako/transport/dispatcher.rb
@@ -109,14 +120,33 @@ def encode_caught_error(error)
       # so the same call site handles both cases without an explicit
       # conditional.
       def invoke(target, method, args, kwargs, yielder = nil)
+        name = method.to_sym
+        reject_meta_method!(target, name)
         block = yielder&.to_proc
         if kwargs.empty?
-          target.public_send(method.to_sym, *args, &block)
+          target.public_send(name, *args, &block)
         else
-          target.public_send(method.to_sym, *args, **kwargs, &block)
+          target.public_send(name, *args, **kwargs, &block)
         end
       end


 # Guard the +public_send+ below against ambient reflection methods



 # (see {META_OWNERS}).



 def reject_meta_method!(target, name)



   owner = target.public_method(name).owner



   return unless META_OWNERS.include?(owner)




   raise UndefinedTargetError, "method #{name.inspect} is not a Service method"



 rescue NameError



   return if target.respond_to?(name)




   raise UndefinedTargetError, "no public method #{name.inspect} on target"



 end</pre>


Fix : The patch introduces a `META_OWNERS` constant listing modules that contain dangerous reflection methods. A new `reject_meta_method!` guard is added to the `invoke` method, which checks if the method being called belongs to one of these meta modules. If so, the call is rejected, preventing guest code from invoking these sensitive methods.

Advisory · Commit


GHSA-p849-8hwh-84j9

CRITICAL 10.0 · 2026-07-31 · JavaScript
@nocobase/plugin-notification-in-app-message · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-2956-977x-2w3r

CRITICAL 10.0 · 2026-07-30 · Python
flyto-core · Pattern: PATH_TRAVERSAL→FILE_WRITE · 57x across ecosystem

Root cause : The application allowed an attacker to control both the target file path and its base directory when writing files. The existing path traversal check was ineffective because it validated the output path against a caller-supplied output directory, which an attacker could manipulate to bypass the check and write files outside the intended sandbox.

Impact : An attacker could write arbitrary files to any location on the file system where the application has write permissions, potentially leading to remote code execution, data corruption, or denial of service.

Diff
-    base_real = os.path.realpath(output_dir)
-    target_real = os.path.realpath(output_path)
-    if os.path.commonpath([base_real, target_real]) != base_real:
-        raise Exception('Invalid file path')
+    try:
+        target_real = validate_path_with_env_config(output_path)
+    except PathTraversalError as e:
+        raise ModuleError(str(e), code="PATH_TRAVERSAL")

Fix : The patch removes the ineffective local path traversal check and replaces it with a centralized `validate_path_with_env_config` utility function. This new function enforces that all file write operations are confined to a secure, operator-configured sandbox directory (`FLYTO_SANDBOX_DIR`), preventing path traversal attacks.

Advisory · Commit


GHSA-4p3g-4hcj-wpvx

CRITICAL 10.0 · 2026-07-29 · Go
github.com/prebid/prebid-server · Pattern: SSRF→INTERNAL_ACCESS · 122x across ecosystem

Root cause : The application was vulnerable to Server-Side Request Forgery (SSRF) because it constructed outbound HTTP requests using user-controlled input (e.g., 'endpoint', 'host', 'account') without sufficient validation. An attacker could manipulate these parameters to make the server send requests to arbitrary internal or external hosts.

Impact : An attacker could force the Prebid Server to make requests to internal network resources, potentially extracting sensitive data from the host environment (e.g., cloud metadata, internal services) or bypassing firewall rules.

Diff
--- /dev/null
+++ b/util/urlutil/security.go
@@ -0,0 +1,12 @@
+package urlutil
+
+import "regexp"
+
+var safeHostPattern = regexp.MustCompile(`^[a-zA-Z0-9.-]+(:[0-9]+)?$`)
+
+// IsSafeHost returns true for bare hostnames with an optional port.
+// It intentionally rejects URL control characters such as '/', '?', '#', and '@'
+// so user-supplied host values cannot rewrite the outbound request URL.
+func IsSafeHost(host string) bool {
+	return safeHostPattern.MatchString(host)
+}
--- adapters/acuityads/acuityads.go
+++ b/adapters/acuityads/acuityads.go
@@ -107,6 +108,9 @@ func (a *AcuityAdsAdapter) buildEndpointURL(params *openrtb_ext.ExtAcuityAds) (string, error) {
}

Fix : The patch introduces a new utility function, `urlutil.IsSafeHost`, which validates user-supplied hostnames to ensure they do not contain URL control characters. This function is then applied to all user-controlled parameters that are used in constructing outbound request URLs, preventing attackers from injecting malicious URLs or paths.

Advisory · Commit


GHSA-f25v-x6vr-962g

CRITICAL 10.0 · 2026-07-24 · PHP
pheditor/pheditor · Pattern: MISSING_AUTH→ENDPOINT · 63x across ecosystem

Root cause : The vulnerability existed because the application had a hardcoded default password 'admin' which, when set, triggered a forced password change flow. During this flow, the application did not verify the current password provided by the user against the actual stored password. Instead, it only checked if the submitted password was 'admin' (which was hardcoded into a hidden input field in the password change form), allowing an attacker to bypass authentication and set a new password without knowing the original one.

Impact : An attacker could completely bypass the authentication mechanism, gain administrative access to the Pheditor application, and potentially execute arbitrary code or modify files on the server, leading to full system compromise.

Diff
--- a/pheditor.php
+++ b/pheditor.php
@@ -152,7 +152,9 @@
if (empty(PASSWORD) === false && (isset($_SESSION['pheditor_admin'], $_SESSION['pheditor_password']) === false || $_SESSION['pheditor_admin'] !== true || $_SESSION['pheditor_password'] != PASSWORD)) {
if (isset($_POST['pheditor_password']) && empty($_POST['pheditor_password']) === false) {


   if (PASSWORD == hash(&#39;sha512&#39;, &#39;admin&#39;)) {





   $submitted_hash = hash(&#39;sha512&#39;, $_POST[&#39;pheditor_password&#39;]);




   if (PASSWORD == hash(&#39;sha512&#39;, &#39;admin&#39;) &amp;&amp; $submitted_hash === PASSWORD) {
       if (isset($_POST[&#39;pheditor_new_password&#39;]) &amp;&amp; isset($_POST[&#39;pheditor_confirm_password&#39;])) {
           if ($_POST[&#39;pheditor_new_password&#39;] === &#39;admin&#39;) {
               $error = &#39;Password cannot be admin&#39;;</pre>


Fix : The patch introduces a check to ensure that when the hardcoded 'admin' password triggers a forced password change, the submitted password hash also matches the actual stored password. This prevents an attacker from simply submitting 'admin' as the current password without knowing the real password, thereby enforcing proper authentication during the password change process.

Advisory · Commit


GHSA-w28w-gp39-m4p6

CRITICAL 10.0 · 2026-07-24 · JavaScript
@prompty/core · Pattern: UNSANITIZED_INPUT→TEMPLATE · 20x across ecosystem

Root cause : The Nunjucks templating engine was used to render user-controlled templates and inputs without sufficient sanitization or sandboxing. This allowed attackers to access and invoke dangerous properties and methods (like `__proto__`, `constructor`, `prototype`) through template expressions, leading to arbitrary code execution.

Impact : An attacker could achieve remote code execution on the server by injecting malicious template code, potentially compromising the entire system.

Diff
--- a/runtime/typescript/packages/core/src/renderers/nunjucks.ts
+++ b/runtime/typescript/packages/core/src/renderers/nunjucks.ts
@@ -13,11 +13,91 @@ import type { Prompty } from "../model/agent/prompty.js";
 import type { Renderer } from "../core/interfaces.js";
 import { prepareRenderInputs } from "./common.js";
+type NunjucksRuntime = {

memberLookup: (object: unknown, property: unknown) => unknown;
callWrap: (callable: unknown, name: string, context: unknown, args: unknown[]) => unknown;
+};


+const UNSAFE_PROPERTIES = new Set(["proto", "constructor", "prototype"]);
+
const env = new nunjucks.Environment(null, {
autoescape: false,
throwOnUndefined: false,
});
+function safeMemberLookup(object: unknown, property: unknown): unknown {

if (typeof property === "string" && UNSAFE_PROPERTIES.has(property)) {
throw new Error(Unsafe template member access: ${property});
}

if (
(typeof property !== "string" && typeof property !== "number") ||
object === null ||
typeof object !== "object"
) {
return undefined;
}

const descriptor = Object.getOwnPropertyDescriptor(object, property);
return descriptor !== undefined && "value" in descriptor ? descriptor.value : undefined;
+}


+function safeCallWrap(_callable: unknown, name: string, _context: unknown, _args: unknown[]): never {

throw new Error(Template function calls are not allowed: ${name});
+}


+function sanitizeValue(value: unknown, seen = new WeakMap<object, unknown>()): unknown {

if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return value;
}

if (typeof value !== "object") {
return undefined;
}

const existing = seen.get(value);
if (existing !== undefined) {
return existing;
}

if (Array.isArray(value)) {
const result: unknown[] = [];
seen.set(value, result);
for (const item of value) {

 result.push(sanitizeValue(item, seen));


}
return result;
}

const result = Object.create(null) as Record<string, unknown>;
seen.set(value, result);
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
if (!UNSAFE_PROPERTIES.has(key) && "value" in descriptor) {

 result[key] = sanitizeValue(descriptor.value, seen);


}
}
return result;
+}


+function sanitizeInputs(inputs: Record<string, unknown>): Record<string, unknown> {

return sanitizeValue(inputs) as Record<string, unknown>;
+}


+function renderSafely(template: string, inputs: Record<string, unknown>): string {

const runtime = nunjucks.runtime as unknown as NunjucksRuntime;
const memberLookup = runtime.memberLookup;
const callWrap = runtime.callWrap;
runtime.memberLookup = safeMemberLookup;
runtime.callWrap = safeCallWrap;

try {
return env.renderString(template, inputs);
} finally {
runtime.memberLookup = memberLookup;
runtime.callWrap = callWrap;
}
+}


export class NunjucksRenderer implements Renderer {
async render(
agent: Prompty,
template: string,
inputs: Record<string, unknown>,
): Promise<string> {
const [modified] = prepareRenderInputs(agent, inputs);

return env.renderString(template, modified);


return renderSafely(template, sanitizeInputs(modified));
}
}

Fix : The patch introduces `safeMemberLookup` and `safeCallWrap` functions to restrict access to unsafe properties and prevent function calls within templates. It also includes `sanitizeValue` and `sanitizeInputs` to recursively clean input data by creating a new object with only safe properties, effectively sandboxing the template rendering environment.

Advisory · Commit


GHSA-v5px-423j-pf7p

CRITICAL 10.0 · 2026-07-08 · Go
github.com/nuclio/nuclio · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-73cv-556c-w3g6

CRITICAL 10.0 · 2026-06-26 · Python
mcp-pinot-server · Pattern: UNSANITIZED_INPUT→SQL · 32x across ecosystem

Root cause : The application allowed unauthenticated users to execute arbitrary SQL queries against the Pinot database. The `oauth_enabled=False` default configuration combined with binding to `0.0.0.0` made the Pinot server publicly accessible without authentication, enabling attackers to send malicious SQL.

Impact : An attacker could execute arbitrary SQL commands, potentially leading to data exfiltration, modification, or deletion, and could also invoke administrative functions or other tools if the underlying database permissions allowed.

Diff
--- a/mcp_pinot/pinot_client.py
+++ b/mcp_pinot/pinot_client.py
@@ -46,6 +49,289 @@ class PinotEndpoints:
     TABLE_CONFIG = "tableConfigs/{}"
+_READ_QUERY_START_KEYWORDS = {"SELECT", "WITH"}
+_PROHIBITED_READ_QUERY_KEYWORDS = {

"ALTER",
"CALL",
"COPY",
"CREATE",
"DELETE",
"DESCRIBE",
"DROP",
"EXEC",
"EXECUTE",
"EXPLAIN",
"EXPORT",
"GRANT",
"IMPORT",
"INSERT",
"INTO",
"LOAD",
"MERGE",
"REFRESH",
"REPLACE",
"RESET",
"REVOKE",
"SET",
"SHOW",
"TRUNCATE",
"UPDATE",
"UPSERT",
"USE",
+}



+def _strip_sql_comments(query: str) -> str:

"""Remove SQL comments while preserving quoted strings and identifiers."""
result: list[str] = []
quote: str | None = None
i = 0

Fix : The patch introduces extensive SQL parsing and validation logic. It defines a set of allowed starting keywords for read queries and a comprehensive list of prohibited keywords for write/administrative operations. It also includes functions to strip comments and split statements, ensuring that only safe read queries are processed.

Advisory · Commit


GHSA-c39w-43gm-34h5

CRITICAL 10.0 · 2026-06-23 · Go
gogs.io/gogs · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-76w7-j9cq-rx2j

CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-m4wx-m65x-ghrr

CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-rp36-8xq3-r6c4

CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 601x 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.

Advisory · Commit


GHSA-v6mx-mf47-r5wg

CRITICAL 10.0 · 2026-05-29 · JavaScript
vm2 · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-g8f2-4f4f-5jqw

CRITICAL 10.0 · 2026-05-11 · JavaScript
@nyariv/sandboxjs · Pattern: TYPE_CONFUSION→BYPASS · 7x 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 &#39;${b as string}&#39; 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.

Advisory · Commit


GHSA-3258-qmv8-frp3

CRITICAL 10.0 · 2026-05-08 · Go
github.com/free5gc/smf · Pattern: MISSING_AUTH→ENDPOINT · 63x 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.

Advisory · Commit


GHSA-q6mh-rqwh-g786

CRITICAL 10.0 · 2026-05-07 · Go
github.com/enchant97/note-mark/backend · Pattern: INSECURE_DEFAULT→CONFIG · 32x 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.

Advisory · Commit


GHSA-246w-jgmq-88fg

CRITICAL 10.0 · 2026-04-22 · Go
github.com/jkroepke/openvpn-auth-oauth2 · Pattern: MISSING_AUTH→ENDPOINT · 63x 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.

Advisory · Commit


GHSA-gph2-j4c9-vhhr

CRITICAL 10.0 · 2026-04-14 · PHP
wwbn/avideo · Pattern: UNSANITIZED_INPUT→XSS · 108x 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.

Advisory · Commit


GHSA-9cp7-j3f8-p5jx

CRITICAL 10.0 · 2026-04-10 · Go
github.com/daptin/daptin · Pattern: PATH_TRAVERSAL→FILE_WRITE · 57x 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.

Advisory · Commit


GHSA-fvcv-3m26-pcqx

CRITICAL 10.0 · 2026-04-10 · JavaScript
axios · Pattern: UNSANITIZED_INPUT→HEADER · 16x 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 [&#34;${header}&#34;]);
}
+}

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.

Advisory · Commit


GHSA-xp7j-h7jc-4w8p

CRITICAL 9.9 · 2026-09-08 · Go
github.com/semaphoreui/semaphore · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The application directly passed user-controlled Git URLs to the `git` command-line utility without proper sanitization or argument separation. An attacker could craft a Git URL starting with a hyphen ('-'), which `git` would interpret as a command-line option rather than a repository path, leading to arbitrary command execution.

Impact : An attacker could execute arbitrary commands on the server where Semaphore U is running, potentially leading to full system compromise, data exfiltration, or denial of service.

Diff
--- a/db_lib/CmdGitClient.go
+++ b/db_lib/CmdGitClient.go
@@ -115,6 +115,7 @@ func (c CmdGitClient) Clone(r GitRepository) error {
 		"--recursive",
 		"--branch",
 		r.Repository.GitBranch,
+		"--end-of-options",
 		r.Repository.GetGitURL(false),
 		dirName)
 }

Fix : The patch introduces a `ValidateGitURL` function that rejects Git URLs starting with a hyphen. This validation is applied when a repository is created or updated. Additionally, the `--end-of-options` argument is added to all `git` commands that take a user-controlled URL, explicitly telling `git` to treat subsequent arguments as positional parameters rather than options.

Advisory · Commit


GHSA-9x44-4gxf-8c25

CRITICAL 9.9 · 2026-08-28 · PHP
pimcore/pimcore · Pattern: UNSANITIZED_INPUT→SQL · 32x across ecosystem

Root cause : The vulnerability stemmed from insufficient validation of user-supplied field names for DataObject class definitions. These field names were directly incorporated into generated PHP class files (as properties, getters/setters, and constants) and used verbatim in SQL ALTER TABLE DDL statements without proper sanitization or quoting. This allowed an attacker to inject arbitrary PHP code or SQL commands by crafting a malicious field name.

Impact : An attacker could achieve remote code execution on the server by injecting PHP code into the generated class files, or execute arbitrary SQL commands, leading to full system compromise, data manipulation, or data exfiltration.

Diff
--- a/models/DataObject/ClassDefinition/Data.php
+++ b/models/DataObject/ClassDefinition/Data.php
@@ -166,6 +167,14 @@ public function getPermissions(): array|string|null
      */
     public function setName(string $name): static
     {
+        if ($name !== '' && !preg_match('/^[a-zA-Z_][a-zA-Z0-9_]{0,62}$/', $name)) {
+            throw new InvalidArgumentException(sprintf('Invalid field name "%s"', $name));
+        }
+
         $this->name = $name;
     return $this;

--- a/models/DataObject/ClassDefinition/Helper/Dao.php
+++ b/models/DataObject/ClassDefinition/Helper/Dao.php
@@ -39,31 +39,31 @@ protected function addIndexToField(DataObject
// multicolumn field
foreach ($columnType as $fkey => $fvalue) {
$indexName = $field->getName().'__'.$fkey;


                   $columnName = &#39;`&#39; . $indexName . &#39;`&#39;;





                   $columnName = $this-&gt;db-&gt;quoteIdentifier($indexName);
                   if ($unique) {
                       if ($isLocalized) {





                           $columnName .= &#39;,`language`&#39;;





                           $columnName .= &#39;,&#39; . $this-&gt;db-&gt;quoteIdentifier(&#39;language&#39;);
                       } elseif ($isFieldcollection) {





                           $columnName .= &#39;,`fieldname`&#39;;





                           $columnName .= &#39;,&#39; . $this-&gt;db-&gt;quoteIdentifier(&#39;fieldname&#39;);
                       }
                   }
                   if ($this-&gt;indexDoesNotExist($table, $prefix, $indexName)) {





                       $this-&gt;db-&gt;executeQuery(&#39;ALTER TABLE `&#39; . $table . &#39;` ADD &#39; . $uniqueStr . &#39;INDEX `&#39; . $prefix . $indexName . &#39;` (&#39; . $columnName . &#39;);&#39;);





                       $this-&gt;db-&gt;executeQuery(&#39;ALTER TABLE &#39; . $this-&gt;db-&gt;quoteIdentifier($table) . &#39; ADD &#39; . $uniqueStr . &#39;INDEX &#39; . $this-&gt;db-&gt;quoteIdentifier($prefix . $indexName) . &#39; (&#39; . $columnName . &#39;);&#39;);
                   }
               }
           } else {
               // single -column field
               $indexName = $field-&gt;getName();





               $columnName = &#39;`&#39; . $indexName . &#39;`&#39;;





               $columnName = $this-&gt;db-&gt;quoteIdentifier($indexName);
               if ($unique) {
                   if ($isLocalized) {





                       $columnName .= &#39;,`language`&#39;;





                       $columnName .= &#39;,&#39; . $this-&gt;db-&gt;quoteIdentifier(&#39;language&#39;);
                   } elseif ($isFieldcollection) {





                       $columnName .= &#39;,`fieldname`&#39;;





                       $columnName .= &#39;,&#39; . $this-&gt;db-&gt;quoteIdentifier(&#39;fieldname&#39;);
                   }
               }
               if ($this-&gt;indexDoesNotExist($table, $prefix, $indexName)) {





                   $this-&gt;db-&gt;executeQuery(&#39;ALTER TABLE `&#39; . $table . &#39;` ADD &#39; . $uniqueStr . &#39;INDEX `&#39; . $prefix . $indexName . &#39;` (&#39; . $columnName . &#39;);&#39;);





                   $this-&gt;db-&gt;executeQuery(&#39;ALTER TABLE &#39; . $this-&gt;db-&gt;quoteIdentifier($table) . &#39; ADD &#39; . $uniqueStr . &#39;INDEX &#39; . $this-&gt;db-&gt;quoteIdentifier($prefix . $indexName) . &#39; (&#39; . $columnName . &#39;);&#39;);
               }
           }
       } else {</pre>


Fix : The patch introduces a regular expression validation for DataObject field names to ensure they adhere to a strict alphanumeric and underscore format, preventing injection of special characters. Additionally, all SQL identifiers (table names, column names, index names) in ALTER TABLE statements are now properly quoted using `db->quoteIdentifier()` to prevent SQL injection.

Advisory · Commit


GHSA-c64q-hj4j-375f

CRITICAL 9.9 · 2026-08-28 · Java
org.yamcs:yamcs-core · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The Yamcs StreamSQL `LIKE` expression directly embedded user-controlled pattern strings into dynamically compiled Java code (via Janino) without proper escaping. This allowed an authenticated attacker to inject arbitrary Java code into the `LikeExpression`'s `fillCode_getValueReturn` method.

Impact : An authenticated attacker could execute arbitrary code on the server, leading to full system compromise, data exfiltration, or denial of service.

Diff
--- a/yamcs-core/src/main/java/org/yamcs/yarch/streamsql/LikeExpression.java
+++ b/yamcs-core/src/main/java/org/yamcs/yarch/streamsql/LikeExpression.java
@@ -23,5 +23,5 @@ public void fillCode_getValueReturn(StringBuilder code) throws StreamSqlExceptio
         code.append("org.yamcs.yarch.streamsql.Utils.like(");
         children[0].fillCode_getValueReturn(code);
         code.append(", \"");
-        code.append(likeClause.pattern);
+        ValueExpression.escapeJavaString(likeClause.pattern, code);
         code.append("\")");

Fix : The patch introduces a static `escapeJavaString` method in `ValueExpression` and applies it to the `likeClause.pattern` before embedding it into the dynamically generated Java code. This ensures that special characters in the user-provided pattern are properly escaped, preventing code injection.

Advisory · Commit


GHSA-pfvc-3p5h-x7h6

CRITICAL 9.9 · 2026-07-31 · Go
github.com/pterodactyl/wings · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-mjqf-28ph-426h

CRITICAL 9.9 · 2026-07-29 · Go
github.com/kube-logging/logging-operator · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The logging operator was vulnerable to Fluentd configuration injection because it did not properly validate or escape user-provided input before incorporating it into Fluentd configuration files. Specifically, newline characters in directive names, types, IDs, labels, log levels, tags, and parameter names, as well as parameter values, could break out of the intended configuration structure, allowing an attacker to inject arbitrary Fluentd directives, including those that execute remote code.

Impact : An attacker could inject arbitrary Fluentd configuration, leading to remote code execution on the Fluentd pods managed by the logging operator. This could compromise the entire Kubernetes cluster where the operator is deployed.

Diff
--- a/pkg/sdk/logging/model/render/fluent.go
+++ b/pkg/sdk/logging/model/render/fluent.go
@@ -44,6 +44,19 @@ func (f *FluentRender) RenderDirectives(directives []types.Directive, indent int
 		if meta.Directive == "" {
 			return fmt.Errorf("directive must have a name %s", meta)
 		}
+		// Structural tokens can't be quoted, so a newline would break out.
+		for _, t := range []struct{ kind, value string }{
+			{"directive name", meta.Directive},
+			{"@type", meta.Type},
+			{"@id", meta.Id},
+			{"@label", meta.Label},
+			{"@log_level", meta.LogLevel},
+			{"tag", meta.Tag},
+		} {
+			if err := validateFluentToken(t.kind, t.value); err != nil {
+				return err
+			}
+		}
 		f.indentedf(indent, "<%s%s>", meta.Directive, tag(meta.Tag))
 		if meta.Type != "" {
 			f.indentedf(indent+f.Indent, "@type %s", meta.Type)
@@ -61,7 +74,10 @@ func (f *FluentRender) RenderDirectives(directives []types.Directive, indent int
 			keys := mapstrstr.Keys(params)
 			sort.Strings(keys)
 			for _, k := range keys {
-				f.indentedf(indent+f.Indent, "%s %s", k, params[k])
+				if err := validateFluentToken("parameter name", k); err != nil {
+					return err
+				}
+				f.indentedf(indent+f.Indent, "%s %s", k, escapeFluentValue(params[k]))
 			}
 		}
 		if sections := d.GetSections(); len(sections) > 0 {

Fix : The patch introduces validation to prevent newline characters in Fluentd structural tokens (directive names, types, IDs, labels, log levels, tags, and parameter names). It also adds an `escapeFluentValue` function to properly quote and escape parameter values that contain newlines or '#' characters, preventing them from being interpreted as structural elements or Ruby interpolations.

Advisory · Commit


GHSA-rjg6-39jm-rgg4

CRITICAL 9.9 · 2026-07-24 · JavaScript
@better-auth/scim · Pattern: MISSING_AUTHZ→RESOURCE · 108x across ecosystem

Root cause : The vulnerability stemmed from the SCIM provider's update functionality not properly validating email uniqueness during user updates (PUT/PATCH operations). An attacker could change a user's email to one already registered by another user, leading to a collision. Additionally, the system did not properly handle user deactivation via the 'active' SCIM attribute, failing to revoke sessions or enforce the deactivation consistently.

Impact : An attacker could take over another user's account by reassigning their email address. They could also maintain access to a deactivated account if their sessions were not properly revoked, or bypass deactivation entirely if the 'admin' plugin was not present.

Diff
--- a/packages/scim/src/routes.ts
+++ b/packages/scim/src/routes.ts
@@ -850,19 +932,37 @@ export const updateSCIMUser = (authMiddleware: AuthMiddleware) =>
 				});
 			}


  	const email = getUserPrimaryEmail(



  		body.userName,



  		body.emails,



  	).toLowerCase();



  	const name = getUserFullName(email, body.name);



  	const emailChanged = email !== user.email;




  	if (emailChanged) {



  		await assertSCIMEmailAvailable(ctx, email, userId);



  	}




  	const userUpdate: Record&lt;string, unknown&gt; = {



  		email,



  		name,



  		updatedAt: new Date(),



  	};



  	if (emailChanged) {



  		// A reassigned email is unverified until the new address is confirmed.



  		userUpdate.emailVerified = false;



  	}



  	if (body.active !== undefined) {



  		userUpdate.banned = body.active === false;



  	}



  	const deactivating = resolveSCIMActiveDeactivation(ctx, userUpdate);



  	const [updatedUser, updatedAccount] =
  		await ctx.context.adapter.transaction&lt;[User | null, Account | null]&gt;(
  			async () =&gt; {





  				const email = getUserPrimaryEmail(body.userName, body.emails);



  				const name = getUserFullName(email, body.name);



  				const updatedUser = await ctx.context.internalAdapter.updateUser(
  					userId,



  					{



  						email,



  						name,



  						updatedAt: new Date(),



  					},





  					userUpdate,
  				);

  				const updatedAccount =



@@ -875,6 +975,10 @@ export const updateSCIMUser = (authMiddleware: AuthMiddleware) =>
},
);


  	if (deactivating) {



  		await ctx.context.internalAdapter.deleteUserSessions(userId);



  	}



  	const userResource = createUserResource(
  		ctx.context.baseURL,
  		updatedUser!,</pre>


Fix : The patch introduces `assertSCIMEmailAvailable` to enforce email uniqueness during user updates. It also adds `resolveSCIMActiveDeactivation` to correctly map SCIM `active` status to the internal `banned` field, revoke user sessions upon deactivation, and ensure the admin plugin is present for deactivation. The `deleteSCIMUser` function was also updated to only delete the global user if no other accounts are linked.

Advisory · Commit


GHSA-gx55-f84r-v3r7

CRITICAL 9.9 · 2026-06-30 · Go
github.com/fission/fission · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-m63v-2g9w-2w6v

CRITICAL 9.9 · 2026-06-30 · Go
github.com/fission/fission · Pattern: PRIVILEGE_ESCALATION→ROLE · 42x across ecosystem

Root cause : The Fission platform allowed users to specify container configurations for environments (Runtime.Container and Builder.Container) that were not subject to the same security context validation as standard PodSpecs. This oversight meant that dangerous security settings like 'privileged=true' or 'allowPrivilegeEscalation=true' could be set in these specific container fields, bypassing existing security checks.

Impact : An attacker could create privileged pods within the Kubernetes cluster, effectively escaping the container sandbox and gaining root-level access to the host or other cluster resources, leading to full cluster compromise.

Diff
--- a/pkg/apis/core/v1/validation.go
+++ b/pkg/apis/core/v1/validation.go
 	errs = errors.Join(errs, ValidatePodSpecSafety("Environment.spec.runtime.podspec", e.Spec.Runtime.PodSpec))
 	errs = errors.Join(errs, ValidatePodSpecSafety("Environment.spec.builder.podspec", e.Spec.Builder.PodSpec))
+	errs = errors.Join(errs, ValidateContainerSafety("Environment.spec.runtime.container", e.Spec.Runtime.Container))
+	errs = errors.Join(errs, ValidateContainerSafety("Environment.spec.builder.container", e.Spec.Builder.Container))
 	return errs

Fix : The patch introduces a new `ValidateContainerSafety` function to explicitly check the security context of individual containers, specifically applying it to the previously unchecked `Runtime.Container` and `Builder.Container` fields in the Environment CRD. Additionally, a sanitization step is added during container merging to strip dangerous security context settings, providing a defense-in-depth measure even if admission webhooks are bypassed.

Advisory · Commit


GHSA-v455-mv2v-5g92

CRITICAL 9.9 · 2026-06-30 · Go
github.com/fission/fission · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-wmgg-3p4h-48x7

CRITICAL 9.9 · 2026-06-30 · Go
github.com/fission/fission · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-9v98-6g37-x9g6

CRITICAL 9.9 · 2026-06-26 · JavaScript
@deepstream/server · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-qf6p-p7ww-cwr9

CRITICAL 9.9 · 2026-06-23 · Go
gogs.io/gogs · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-5pm9-r2m8-rcmj

CRITICAL 9.9 · 2026-06-22 · PHP
paymenter/paymenter · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause : The application allowed users to upload files via the EasyMDE editor in ticket creation and viewing forms. The `completeUpload` method in Livewire components directly stored these uploaded files without sufficient validation of their content or type, allowing an attacker to upload malicious executable files.

Impact : An attacker could upload a malicious file (e.g., a PHP script) to the server and then execute it, leading to full compromise of the server.

Diff
--- a/themes/default/views/components/easymde-editor.blade.php
+++ b/themes/default/views/components/easymde-editor.blade.php
@@ -8,7 +8,7 @@
             element: document.getElementById('editor'),
             spellChecker: false,
             previewImagesInEditor: true,
-            uploadImage: true,
+            uploadImage: false,
             autoDownloadFontAwesome: false,
             status: [{
                 className: 'upload-image',
@@ -45,11 +45,6 @@ className: 'upload-image',
                     name: 'ordered-list',
                     action: EasyMDE.toggleOrderedList,
                 }, '|',
-                {
-                    name: 'upload-image',
-                    action: EasyMDE.drawUploadedImage,
-                    title: 'Upload Image',
-                }, '|',
                 {
                     name: 'undo',
                     action: EasyMDE.undo,
@@ -59,13 +54,6 @@ className: 'upload-image',
                 },
         ],



       imageUploadFunction: async (file, onSuccess, onError) =&gt; {



           @this.upload(&#39;attachments&#39;, file, (url) =&gt; {



               @this.completeUpload(url).then((url) =&gt; {



                   onSuccess(url);



               });



           });



       },
   });</pre>


Fix : The patch removes the file upload functionality from the EasyMDE editor in ticket forms by disabling the `uploadImage` option and removing the associated `imageUploadFunction`. It also removes the `WithFileUploads` trait and related attachment handling logic from the Livewire components, effectively preventing any file uploads through these interfaces.

Advisory · Commit


GHSA-jvc5-6g7q-c843

CRITICAL 9.9 · 2026-06-09 · PHP
pheditor/pheditor · Pattern: UNSANITIZED_INPUT→COMMAND · 94x 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.

Advisory · Commit


GHSA-598g-h2vc-h5vg

CRITICAL 9.9 · 2026-06-08 · Go
github.com/juev/nebula-mesh · Pattern: PRIVILEGE_ESCALATION→ROLE · 42x 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(&#34;isActiveAdmin: store lookup&#34;, &#34;operator&#34;, captured.ID, &#34;error&#34;, 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.

Advisory · Commit


GHSA-fqvv-jvhr-g5jc

CRITICAL 9.9 · 2026-05-05 · Python
firefighter-incident · Pattern: SSRF→CLOUD_METADATA · 3x 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. &#34;[&#39;https://a&#39;, &#39;https://b&#39;]&#34;)
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&#34;Attachment URL exceeds {ATTACHMENT_URL_MAX_LENGTH} characters.&#34;



   raise serializers.ValidationError(msg)


parsed = urlparse(url)
if parsed.scheme not in ATTACHMENT_ALLOWED_SCHEMES:

   msg = f&#34;Attachment URL scheme &#39;{parsed.scheme}&#39; is not allowed.&#34;



   raise serializers.ValidationError(msg)


host = parsed.hostname
if not host:

   raise serializers.ValidationError(&#34;Attachment URL is missing a host.&#34;)


try:

   addr_infos = socket.getaddrinfo(host, None)


except socket.gaierror as err:

   msg = f&#34;Attachment URL host &#39;{host}&#39; could not be resolved.&#34;



   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(



           &#34;Attachment URL host resolves to a private, loopback or link-local address.&#34;



       )





class IgnoreEmptyStringListField(serializers.ListField):
def to_internal_value(self, data: list[Any] | Any) -> list[str]:
# Check if data is a list

Fix : 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.

Advisory · Commit


GHSA-xwwr-4h3p-r22c

CRITICAL 9.8 · 2026-09-10 · Go
github.com/rclone/rclone · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-92f5-vc22-8j33

CRITICAL 9.8 · 2026-09-08 · C#
Microsoft.Native.Quic.MsQuic.Schannel · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause : The vulnerability existed because the QUIC implementation did not properly validate the state of a network path when processing incoming packets. An attacker could send specially crafted packets that would cause the system to attempt to use an inactive or invalid path, leading to memory corruption.

Impact : An attacker could achieve remote code execution on the target system by exploiting the memory corruption, allowing them to execute arbitrary code with the privileges of the QUIC process.

Diff
--- a/src/core/connection.c
+++ b/src/core/connection.c
@@ -5458,7 +5458,7 @@ QuicConnRecvPostProcessing(
 if (Packet-&gt;HasNonProbingFrame &amp;&amp;
     Packet-&gt;NewLargestPacketNumber &amp;&amp;



   !(*Path)-&gt;IsActive) {





   !(*Path)-&gt;IsActive &amp;&amp; (*Path)-&gt;InUse) {</pre>


Fix : The patch adds an additional check to ensure that a network path is not only inactive but also 'InUse' before proceeding with path switching logic. This prevents the system from attempting to use a path that is not properly initialized or valid, thereby mitigating the memory corruption vulnerability.

Advisory · Commit


GHSA-rcr6-4jqh-j84m

CRITICAL 9.8 · 2026-09-08 · Go
gitea.dev · Pattern: UNCLASSIFIED · 601x across ecosystem

Root cause :

Impact :

Fix :

Advisory · Commit


GHSA-w6f5-v2h6-g786

CRITICAL 9.8 · 2026-09-08 · PHP
predis/predis · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The vulnerability stemmed from how Predis handled pipelined commands, particularly in aggregate connections (like Redis Cluster). It would concatenate all serialized commands into a single buffer and then write this buffer to the connection. This batching, combined with the lack of proper CRLF (carriage return and line feed) sanitization, allowed an attacker to inject arbitrary Redis commands by smuggling CRLF sequences within a command argument, effectively terminating the current command and starting a new one.

Impact : An attacker could inject arbitrary Redis commands, leading to data manipulation, unauthorized access, or even remote code execution if the Redis server is configured to load modules or execute Lua scripts. Additionally, by injecting malformed commands or a large number of commands, an attacker could trigger a denial of service condition on the Redis server.

Diff
--- a/src/Pipeline/ConnectionErrorProof.php
+++ b/src/Pipeline/ConnectionErrorProof.php
@@ -92,14 +92,12 @@ protected function executeCluster(ClusterInterface $connection, SplQueue $comman
         $responses = [];
         $sizeOfPipe = count($commands);
         $exceptions = [];
-        $buffer = '';
     foreach ($commands as $command) {



       $buffer .= $command-&gt;serializeCommand();





       $nodeConnection = $connection-&gt;getConnectionByCommand($command);



       $nodeConnection-&gt;write($command-&gt;serializeCommand());
   }





   $connection-&gt;write($buffer);



   for ($i = 0; $i &lt; $sizeOfPipe; ++$i) {</pre>


Fix : The patch refactors the command writing logic for pipelined commands. Instead of buffering all commands and writing them in one go, it now iterates through each command and writes it individually to the appropriate node connection, especially for aggregate connections. This prevents CRLF smuggling by ensuring each command is sent as a distinct unit, rather than being part of a larger, potentially injectable buffer.

Advisory · Commit


GHSA-2v6v-25fm-p4fg

CRITICAL 9.8 · 2026-09-02 · Go
github.com/seaweedfs/seaweedfs · Pattern: MISSING_AUTH→ENDPOINT · 63x across ecosystem

Root cause : The SeaweedFS filer's IAM gRPC service endpoints, which manage S3 users and access keys, lacked any authentication mechanism. This allowed any unauthenticated client to invoke administrative functions.

Impact : An attacker could create, modify, or delete S3 users and their access keys, effectively gaining full administrative control over the S3-compatible storage and potentially accessing or manipulating all stored data.

Diff
--- a/weed/server/filer_server_handlers_iam_grpc.go
+++ b/weed/server/filer_server_handlers_iam_grpc.go
@@ -32,6 +32,30 @@
func NewIamGrpcServer(credentialManager *credential.CredentialManager) *IamGrpcServer {
return &IamGrpcServer{
credentialManager: credentialManager,


  adminSigningKey:   adminSigningKey,

}
}

+func (s *IamGrpcServer) checkAdminAuth(ctx context.Context) error {

if len(s.adminSigningKey) == 0 {

  return status.Error(codes.PermissionDenied, &#34;iam admin auth not configured&#34;)


}
md, ok := metadata.FromIncomingContext(ctx)
if !ok {

  return status.Error(codes.Unauthenticated, &#34;missing metadata&#34;)


}
authHeaders := md.Get("authorization")
if len(authHeaders) == 0 {

  return status.Error(codes.Unauthenticated, &#34;missing authorization metadata&#34;)


}
raw := strings.TrimSpace(authHeaders[0])
parts := strings.Fields(raw)
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || parts[1] == "" {

  return status.Error(codes.Unauthenticated, &#34;authorization header must use Bearer scheme&#34;)


}
token := parts[1]
parsed, err := security.DecodeJwt(s.adminSigningKey, security.EncodedJwt(token), &security.SeaweedFilerAdminClaims{})
if err != nil || parsed == nil || !parsed.Valid {

  return status.Error(codes.Unauthenticated, &#34;invalid admin token&#34;)


}
return nil
+}


//////////////////////////////////////////////////
// Configuration Management
func (s *IamGrpcServer) GetConfiguration(ctx context.Context, req *iam_pb.GetConfigurationRequest) (*iam_pb.GetConfigurationResponse, error) {

if err := s.checkAdminAuth(ctx); err != nil {

  return nil, err


}
if req == nil {

  return nil, status.Errorf(codes.InvalidArgument, &#34;request is required&#34;)


}
glog.V(4).Infof("GetConfiguration")

Fix : The patch introduces a `checkAdminAuth` method that verifies a Bearer token signed by a pre-configured filer write-signing key. This method is now called at the beginning of every IAM gRPC service handler to ensure only authenticated and authorized requests are processed.

Advisory · Commit


GHSA-m4rf-3fr8-xwx3

CRITICAL 9.8 · 2026-09-01 · Python
nltk · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The vulnerability stemmed from an incomplete fix for a previous JVM argument injection issue. The `_validate_java_options` function, intended to sanitize JVM arguments, did not adequately restrict per-call options, allowing an attacker to inject dangerous JVM flags like `-XX:OnError` or `-D` system properties. This bypass enabled the execution of arbitrary commands or other malicious actions.

Impact : An attacker could achieve arbitrary command execution on the system running the NLTK application by injecting specially crafted JVM arguments. This could lead to full system compromise, data exfiltration, or denial of service.

Diff
--- a/nltk/internals.py
+++ b/nltk/internals.py
@@ -43,23 +59,64 @@
     "-xcomp",  # compile-only mode
     "-xmixed",  # mixed mode (JVM default)
     "-verbose",  # diagnostic output: -verbose:gc
-    "-xx:",  # advanced tuning:  -XX:+UseG1GC
+
 ) 
_SAFE_JVM_EXACT = frozenset({"-server", "-client"})
+# --add-modules &lt;module-list&gt; is required by CoreNLP on JDK 9-11 (a CoreNLP
+# dependency uses the JAXB module dropped from the default set). The value is a
+# comma-separated list of module names -- it names JDK modules, and because
+# --module-path / -p is NOT allowlisted it cannot point at attacker code.
+# Restrict the value to a plain module-list shape so nothing else rides through.
+MODULE_LIST_RE = re.compile(r"\A[A-Za-z0-9.,-]+\Z")
+
+# Every flag the allowlist accepts (heap/stack sizing, -verbose, -server/-client,
+# --add-modules) is a single simple token; none contains whitespace or a shell
+# metacharacter. Rejecting those characters is therefore a free, name-agnostic
+# defense-in-depth layer (it has no false positives now that -D, whose values may
+# legitimately contain them, is not accepted): e.g. a malformed -Xmx512m ; rm
+# token cannot ride through on the -xmx prefix.
+_UNSAFE_OPTION_CHARS = frozenset(" \t\r\n;|&$`<>()[]*?!'&#34;\")
def _validate_java_options(options):
"""

Raise ValueError if options contains JVM flags that can change
the executed program, load agents, or expand argument files.

Uses an allowlist of safe JVM memory/tuning flags that NLTK's Java
wrapper is known to need.  This is intentionally stricter than a
denylist so that -jar, @argfile, and future dangerous flags are
rejected without needing to be enumerated (CVE-2026-12841, CWE-88).


Raise ValueError if options contains JVM flags that can change the
executed program, run a command, load agents, or expand argument files.

Uses a minimal allowlist of exactly the flags NLTK's Java wrappers and the
Stanford CoreNLP documentation use (heap/stack sizing, -verbose,
-server/-client, and --add-modules). This is intentionally stricter than
a denylist so that -jar, @argfile, -XX:OnError=&lt;cmd&gt;, dangerous -D
system properties, and future dangerous flags are all rejected without
needing to be enumerated (CVE-2026-12841, CWE-88). Applications needing an
unlisted flag use java(..., trusted_raw_options=[...]).
"""


for flag in options:


opts = list(options)
i = 0
while i < len(opts):

   flag = opts[i]




   # A JVM flag is a non-empty string; anything else cannot be reasoned



   # about safely, so reject it rather than call .lower() on it.



   if not isinstance(flag, str) or not flag:



       raise ValueError(



           f&#34;java_options contains an invalid (non-string or empty) entry: &#34;



           f&#34;{flag!r} (CVE-2026-12841, CWE-88).&#34;



       )




   # Shape guard: no legitimate allowed flag contains whitespace, a control



   # character, or a shell metacharacter; reject any that does.



   if any(



       c.isspace() or ord(c) &lt; 0x20 or ord(c) == 0x7F or c in _UNSAFE_OPTION_CHARS



       for c in flag



   ):



       raise ValueError(



           f&#34;java_options contains whitespace, a control character, or a &#34;



           f&#34;shell metacharacter, which a valid JVM flag never does: &#34;



           f&#34;{flag!r} (CVE-2026-12841, CWE-88).&#34;



       )



   n = flag.lower()

   # @argfile references are expanded by the Java launcher before



@@ -70,21 +127,38 @@ def _validate_java_options(options):
f"reference: {flag!r} (CVE-2026-12841, CWE-88)."
)


   # Allow -Dkey=value system properties. The prefix is always



   # uppercase -D in valid usage; check the original flag.



   if flag.startswith(&#34;-D&#34;) and &#34;=&#34; in flag:





   # --add-modules &lt;modules&gt;  (two tokens) or  --add-modules=&lt;modules&gt;.



   if n == &#34;--add-modules&#34;:



       mods = opts[i + 1] if i + 1 &lt; len(opts) else None



       if not isinstance(mods, str) or not _MODULE_LIST_RE.match(mods):



           raise ValueError(



               f&#34;--add-modules must be followed by a plain module list, got &#34;



               f&#34;{mods!r} (CVE-2026-12841, CWE-88).&#34;



           )



       i += 2



       continue



   if n.startswith(&#34;--add-modules=&#34;):



       if not _MODULE_LIST_RE.match(flag.split(&#34;=&#34;, 1)[1]):



           raise ValueError(



               f&#34;--add-modules has a non-module-list value: {flag!r} &#34;



               &#34;(CVE-2026-12841, CWE-88).&#34;



           )



       i += 1
       continue

   if n in _SAFE_JVM_EXACT:



       i += 1
       continue

   if n.startswith(_SAFE_JVM_PREFIXES):



       i += 1
       continue

   raise ValueError(
       f&#34;java_options contains a disallowed JVM/launcher flag: {flag!r}. &#34;





       &#34;Only JVM memory-tuning and safe runtime flags are permitted &#34;



       &#34;(CVE-2026-12841, CWE-88).&#34;





       &#34;Only JVM memory/stack tuning, -verbose, -server/-client and &#34;



       &#34;--add-modules are permitted; pass anything else through &#34;



       &#34;java(trusted_raw_options=...) (CVE-2026-12841, CWE-88).&#34;
   )



@@ -209,4 +297,10 @@ def java(
if isinstance(options, str):
options = options.split()
java_options = list(options)


   # Per-call options reach subprocess.Popen directly, so they must be



   # validated too -- config_java() alone is not enough (CVE-2026-12841,



   # CWE-88). Without this a caller-supplied -jav</pre>


Fix : The patch significantly tightens the allowlist for JVM arguments, explicitly removing `-XX:` and `-D` prefixes, which were previously allowed. It also adds new validation checks for unsafe characters and ensures that per-call options are also subjected to the same strict validation as global options, preventing the bypass of the original fix.

Advisory · Commit


GHSA-73mf-m39p-wpm9

CRITICAL 9.8 · 2026-08-28 · Java
org.yamcs:yamcs-core · Pattern: UNSANITIZED_INPUT→TEMPLATE · 20x across ecosystem

Root cause : The vulnerability stemmed from the Yamcs server processing user-controlled input as part of an instance-template argument, which was then directly fed into a YAML parser. This allowed an attacker to inject arbitrary YAML, including directives that could lead to object instantiation and method invocation, effectively achieving Remote Code Execution.

Impact : An attacker could achieve arbitrary code execution on the server running Yamcs, leading to full compromise of the system, including data theft, modification, or denial of service.

Diff
--- a/yamcs-core/src/main/java/org/yamcs/templating/Template.java
+++ b/yamcs-core/src/main/java/org/yamcs/templating/Template.java
@@ -47,6 +52,66 @@ public String process(Map<String, Object> args) {
         return templateProcessor.process(args);
     }

public String processAndSanitizeYaml(Map<String, Object> userArgs) {

   Map&lt;String, Object&gt; tokenArgs = new HashMap&lt;&gt;();</pre>


Fix : The patch introduces a sanitization layer for YAML processing. It replaces user-provided string arguments with unique UUID tokens before template processing. After the template is rendered, the output is parsed into a YAML object structure, and then the tokens are safely replaced with their original string values. This ensures that user input is treated as data and not as executable YAML directives.

Advisory · Commit


GHSA-jrw6-7x4q-w25j

CRITICAL 9.8 · 2026-08-26 · Python
senaite.core · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The application used Python's `eval()` function to parse stringified record values from user-controlled input. The `eval()` function executes arbitrary Python code, making it highly dangerous when used with untrusted input.

Impact : An attacker could achieve arbitrary code execution on the server, leading to full system compromise, data exfiltration, or denial of service.

Diff
--- a/src/senaite/core/browser/fields/record.py
+++ b/src/senaite/core/browser/fields/record.py
@@ -253,7 +254,7 @@ def labelFax(self,fax=''):
     def set(self, instance, value, **kwargs):
         if type(value) in StringTypes:
             try:
-                value = eval(value)
+                value = parse_record_literal(value)

Fix : The patch replaces all instances of `eval()` with `ast.literal_eval()`. A new utility function `parse_record_literal` was introduced to encapsulate this safe parsing, ensuring that only Python literal structures (strings, numbers, tuples, lists, dicts, booleans, and None) can be evaluated, preventing arbitrary code execution.

Advisory · Commit


GHSA-mw6r-2hvm-4rp2

CRITICAL 9.8 · 2026-08-25 · Python
qwed-mcp · Pattern: UNSANITIZED_INPUT→COMMAND · 94x across ecosystem

Root cause : The application used SymPy's `parse_expr()` function to evaluate user-supplied mathematical expressions without sufficient sanitization or a restricted execution environment. This allowed attackers to inject arbitrary Python code, which `parse_expr()` would then execute.

Impact : An attacker could execute arbitrary Python code on the server, leading to full system compromise, data exfiltration, or denial of service.

Diff
--- a/src/qwed_mcp/engines/math_engine.py
+++ b/src/qwed_mcp/engines/math_engine.py
@@ -17,29 +19,19 @@ def verify_math_expression(
     Returns:
         Verification result with verified status and details
     """
     try:
         from sympy import (
-            symbols, sympify, diff, integrate, simplify, solve,
-            Eq, parse_expr, sqrt, sin, cos, exp, log, pi, E
+            symbols, diff, integrate, simplify, solve, Eq,
         )
-        from sympy.parsing.sympy_parser import (
-            parse_expr, standard_transformations,
-            implicit_multiplication_application, convert_xor
-        )
-
         # Common symbol
         x, y, z = symbols('x y z')
-
-        # Transformation for parsing
-        transformations = standard_transformations + (
-            implicit_multiplication_application,
-            convert_xor,
-        )
-
         # Parse expression
         try:
-            expr = parse_expr(
-                expression.replace("^", "**"),
-                local_dict={"x": x, "y": y, "z": z, "pi": pi, "e": E},
-                transformations=transformations
-            )
+            expr = safe_parse_expr(expression.replace("^", "**"))
         except Exception as e:
             return {
                 "verified": False,
                 "message": f"Could not parse expression: {expression}",
                 "error": str(e)
             }
-
         # Parse claimed result
         try:
-            claimed = parse_expr(
-                claimed_result.replace("^", "**"),
-                local_dict={"x": x, "y": y, "z": z, "pi": pi, "e": E},
-                transformations=transformations
-            )
+            claimed = safe_parse_expr(claimed_result.replace("^", "**"))
         except Exception as e:

Fix : A new `safe_parser.py` module was introduced, containing `safe_parse_expr()`. This function implements a denylist for dangerous keywords, restricts the global and local dictionaries available during parsing, and enforces a maximum expression length. The `math_engine.py` was updated to use this new safe parser.

Advisory · Commit


How it works

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 50 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
ComponentTechNotes
AutomationGitHub Actions cronZero infra
Data sourceGitHub Advisory DBGraphQL, filtered on patch commits
LLMGemini 2.5 FlashFree tier, JSON-only output
DBSQLite rebuilt from JSONLGit-friendly, versioned
FrontendStatic HTMLClient-side search, zero build step
ScriptingPython 3.11requests, jinja2, sqlite3
Stats
MetricValue
Total advisories1961
Unique patterns50
Pending42
Last updated2026-09-13

christbowel.com

About

Automated patch intelligence - tracks what gets fixed in open source daily, extracts vulnerability patterns, and detects recurring antipatterns across languages and ecosystems. Powered by GitHub Advisory DB + Gemini.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages