# Ziti Admin Console (ZAC) Node server: unauthenticated /api/send endpoint allows file read and mail relay

**URL:** <https://openziti.discourse.group/t/ziti-admin-console-zac-node-server-unauthenticated-api-send-endpoint-allows-file-read-and-mail-relay/6145>\
**Category:** Security Adivsories\
**Created:** [September 29, 2026, 7:50pm UTC](https://openziti.discourse.group/t/ziti-admin-console-zac-node-server-unauthenticated-api-send-endpoint-allows-file-read-and-mail-relay/6145 "2026-09-29T19:50:30Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![rgalletto](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/rgalletto/32/1508_2.png) [@rgalletto](https://openziti.discourse.group/u/rgalletto)\
**Post date:** [September 29, 2026, 7:50pm UTC](https://openziti.discourse.group/t/ziti-admin-console-zac-node-server-unauthenticated-api-send-endpoint-allows-file-read-and-mail-relay/6145/1 "2026-09-29T19:50:30Z")

</div>

## Summary

The ZAC Node backend exposes an unauthenticated `POST /api/send` endpoint that passes the request body, including the recipient and the `attachments` array, straight into nodemailer's `sendMail`. Because nodemailer reads a `{path}` attachment from local disk and fetches a `{href}` attachment from a URL, an unauthenticated attacker can exfiltrate server files by email, relay mail through the configured SMTP server, or trigger server-side requests.

## Affected Component

- **Package:** `openziti/ziti-console` (Ziti Admin Console) — Node backend
- **File:** `server.js` — the `/api/send` handler (and the related `/api/message` handler)
- **Sink:** attacker-controlled recipient and `attachments` passed to nodemailer `sendMail`

## Vulnerability Class

- **Primary:** CWE-306 — Missing Authentication for Critical Function
- **Secondary:** CWE-73 — External Control of File Name or Path (file read); CWE-918 — Server-Side Request Forgery

## Attacker Model

An unauthenticated remote attacker with network access to the ZAC Node server. No credentials and no user interaction are required.

## Preconditions

ZAC running via the Node backend (`server.js`) in `node-api` or `classic` mode, **with an SMTP transporter configured** (`settings.mail.host` set). Deployments that serve only the static Angular application, or that have no SMTP configured, are **not** affected.

## Root Cause

`/api/send` builds the mail from the request body without authentication, taking both the recipient and the raw nodemailer `attachments` objects from the caller. nodemailer treats a `{path:"..."}` attachment as a local file to read and a `{href:"..."}` attachment as a URL to fetch, so the caller controls which file is read (or URL fetched) and where it is delivered.

## Impact

Because both the recipient and the attachment objects come from the request, an unauthenticated attacker can abuse the endpoint three ways:

1. **Read server files via email.** A `{path}` attachment makes the server read that file (as raw bytes, so any accessible file) and email it to an attacker-chosen address — including `settings.json` (SMTP credentials) and session files holding controller session tokens that can be replayed against the controller.
2. **Open mail relay.** The attacker chooses the recipient and content, turning the configured SMTP server into a relay for spam or phishing.
3. **SSRF.** A `{href}` attachment makes the server fetch an arbitrary URL from the Node host.

The related `POST /api/message` endpoint shares the missing authentication but sends only to a fixed recipient and has no attachment sink, so its impact is limited to unauthenticated mail to that fixed address.

- **CVSS v3.1:** 8.6 (High)
- **Vector:** `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N`

**Not impacted:** static-only (SPA) deployments, or deployments with no SMTP configured; no remote code execution.

## Package

`openziti/ziti-console` (app-ziti-console, Node backend / `node-api` mode)

## Affected Versions

- app-ziti-console `< 4.5.3`

## Patched Versions

- app-ziti-console `4.5.3`

## Remediation

Upgrade to 4.5.3, which removes the unused `/api/send` and `/api/message` handlers (the console builds and sends enrollment email content client-side, so they were dead code). If you cannot upgrade: leave SMTP unconfigured (`settings.mail.host` unset), block `POST /api/send` and `POST /api/message` at a reverse proxy, or run ZAC in static-asset (SPA) mode instead of the Node proxy.

## References

- GHSA: [https://github.com/openziti/ziti-console/security/advisories/GHSA-mwjf-9478-gjmc](https://github.com/openziti/ziti-console/security/advisories/GHSA-mwjf-9478-gjmc)
- CVE: (pending)

## Credits

Reported by dmuensterer and sajdakabir.
