appleboy / appleboy/gorush

Missing Authentication on HTTP API Allows Unauthenticated Push Notification Abuse

Open
#877 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
8.8k
Forks
887
PR merge metrics
No merged PRs in 30d

Description

### Summary

Gorush exposes its entire HTTP REST API without any authentication mechanism. Any unauthenticated network client can call `POST /api/push` to send arbitrary push notifications through the server operator's FCM, APNS, or HMS credentials. Additional endpoints expose server configuration and runtime metrics without access control, including `GET /api/config` which leaks the Huawei App ID and queue/stat backend addresses.

### Details

The Gin router in `router/server.go` (`routerEngine` function, line 168-221) registers all routes with no authentication middleware. The global middleware stack consists only of a logger, recovery handler, a version header setter, and a statistics collector -- there is no token, bearer, basic-auth, or API-key check anywhere in the codebase:

```go
// router/server.go lines 196-217
r.Use(logger.SetLogger(...))
r.Use(gin.Recovery())
r.Use(VersionMiddleware())
r.Use(StatMiddleware())

r.GET(cfg.API.StatGoURI, api.GinHandler) // /api/stat/go
r.GET(cfg.API.StatAppURI, appStatusHandler(q)) // /api/stat/app
r.GET(cfg.API.ConfigURI, configHandler(cfg)) // /api/config
r.GET(cfg.API.SysStatURI, sysStatsHandler()) // /sys/stats
r.POST(cfg.API.PushURI, pushHandler(cfg, q)) // /api/push
r.GET(cfg.API.MetricURI, metricsHandler) // /metrics
r.GET(cfg.API.HealthURI, heartbeatHandler) // /healthz
```

The `pushHandler` (line 59-105) accepts a JSON notification batch, validates only structure and count, then immediately enqueues the notifications for delivery via `handleNotification`. The FCM/APNS/HMS client used is the globally-initialized server credential -- the caller supplies only device tokens and message content. A remote unauthenticated attacker who can reach port 8088 (the documented default) can send push notifications to any device token through the operator's credentials.

The `configHandler` (line 107-111) calls `cfg.SanitizedCopy()` before responding. The `SanitizedCopy` function in `config/config.go` (line 462-503) redacts most secrets but leaves `Huawei.AppID` and `Core.FeedbackURL` in plaintext, disclosing these values to any unauthenticated caller.

The default bind address (`cfg.Core.Address`) is an empty string, which causes the Go HTTP server to listen on `0.0.0.0` (all interfaces). The official Docker quick-start in the README publishes this port directly: `docker run -d --name gorush -p 8088:8088 appleboy/gorush`. The "Security Best Practices" section in the README does not mention authentication or access control.

### PoC

(available upon request)

### Impact

Any unauthenticated network client that can reach port 8088 can send arbitrary push notifications through the operator's FCM service account, APNS certificate, or HMS app credentials. This enables notification spam to real users (phishing, harassment, credential-harvesting lures), exhaustion of platform push quotas (FCM/APNS rate limits apply per-credential), and impersonation of the application operator. Deployments following the documented quick-start (`docker run -d --name gorush -p 8088:8088 appleboy/gorush`) are immediately exploitable from the public internet with no preconditions.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in router/server.go at routerEngine and review the middleware and route registrations, then inspect config/config.go for SanitizedCopy and the README Docker quick-start. Determine the authentication and access-control design before changing the public API. Done should prevent unauthenticated push and sensitive configuration access while preserving the intended health or metrics behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
api, backend, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.