Every CVE Search/ Get API key

CVE-2026-79667

Ech0 before 4.4.3 Authentication Bypass via Scope Enforcement

7.2 HighFix available

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
Low
Availability
Low

Exploit likelihood

0.32%Up 0.1 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.2

Ech0 before 4.4.3 Authentication Bypass via Scope Enforcement

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Record
CVE-2026-79667
CVSS 4.0
7.2 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:L/SC:N/SI:N/SA:N
CVSS 3.1
7.6 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Weakness
CWE-285
Updated
2026-11-02
EUVDEUVD-2026-65447 7.2

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Record
EUVD-2026-65447
CVSS 4.0
7.2 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:L/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-4h9q-p5j4-xvvh 7.6

Ech0: Scoped admin access tokens can bypass least-privilege controls on privileged endpoints, including backup export

Summary

Ech0 scoped access tokens do not reliably enforce least privilege: multiple privileged admin routes omit scope checks, and the backup export handler strips token scope metadata entirely, allowing a low-scope admin access token to reach broader admin functionality than intended.

Impact

An attacker who obtains a deliberately limited access token for an admin account can use that token to access privileged functionality outside its assigned scope. Confirmed impact includes access to /api/inbox with a token scoped only for echo:read and successful backup export via /api/backup/export?token=..., which returns a full ZIP archive. In practice, this turns a narrowly delegated API token into a broader privileged access and data exfiltration primitive.

Details

The issue is caused by a split authorization model:

  • JWTAuthMiddleware() authenticates the token and stores scope metadata in the viewer context
  • RequireScopes(...) enforces least privilege, but only when a route explicitly adds it
  • several privileged routes omit RequireScopes(...)
  • multiple service methods then authorize using only user.IsAdmin

internal/middleware/scope.go shows that scope enforcement is opt-in:

func RequireScopes(scopes ...string) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		v := viewer.MustFromContext(ctx.Request.Context())
		if v.TokenType() == authModel.TokenTypeSession {
			ctx.Next()
			return
		}
		if v.TokenType() != authModel.TokenTypeAccess { ... }
		if !containsValidAudience(v.Audience()) { ... }
		if !containsAllScopes(v.Scopes(), scopes) { ... }
		ctx.Next()
	}
}

Representative privileged routes omit RequireScopes(...), for example internal/router/inbox.go:

func setupInboxRoutes(appRouterGroup *AppRouterGroup, h *handler.Bundle) {
	appRouterGroup.AuthRouterGroup.GET("/inbox", h.InboxHandler.GetInboxList())
	appRouterGroup.AuthRouterGroup.GET("/inbox/unread", h.InboxHandler.GetUnreadInbox())
	appRouterGroup.AuthRouterGroup.PUT("/inbox/:id/read", h.InboxHandler.MarkInboxAsRead())
	appRouterGroup.AuthRouterGroup.DELETE("/inbox/:id", h.InboxHandler.DeleteInbox())
	appRouterGroup.AuthRouterGroup.DELETE("/inbox", h.InboxHandler.ClearInbox())
}

Other source-confirmed unguarded privileged surfaces include:

  • /api/panel/comments*
  • /api/addConnect
  • /api/delConnect/:id
  • /api/migration/*
  • /api/backup/export

Service-layer authorization often checks only admin role. For example, internal/service/inbox/inbox.go:

func (inboxService *InboxService) ensureAdmin(ctx context.Context) error {
	userid := viewer.MustFromContext(ctx).UserID()
	user, err := inboxService.commonService.CommonGetUserByUserId(ctx, userid)
	if err != nil {
		return err
	}
	if !user.IsAdmin {
		return errors.New(commonModel.NO_PERMISSION_DENIED)
	}
	return nil
}

The backup export path is a stronger variant because it discards token metadata before authorization. internal/handler/backup/backup.go reparses a query token and rebuilds a bare viewer from only the user ID:

func (backupHandler *BackupHandler) ExportBackup() gin.HandlerFunc {
	return res.Execute(func(ctx *gin.Context) res.Response {
		token := ctx.Query("token")
		claims, err := jwtUtil.ParseToken(token)
		if err != nil { ... }

		reqCtx := viewer.WithContext(context.Background(), viewer.NewUserViewer(claims.Userid))
		if err := backupHandler.backupService.ExportBackup(ctx, reqCtx); err != nil { ... }
		return res.Response{Msg: commonModel.EXPORT_BACKUP_SUCCESS}
	})
}

This drops token type, scopes, audience, and token ID before the backup service runs.

Proof of concept

1. Start the app

docker run -d \
  --name ech0 \
  -p 6277:6277 \
  -v /opt/ech0/data:/app/data \
  -e JWT_SECRET="Hello Echos" \
  sn0wl1n/ech0:latest

2. Initialize an owner account

curl -sS -X POST "http://127.0.0.1:6277/api/init/owner" \
  -H 'Content-Type: application/json' \
  -d…
Record
GHSA-4h9q-p5j4-xvvh
CVSS 3.1
7.6 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Weakness
CWE-285
Updated
2026-11-02
GitHub AdvisoriesGHSA-vgpj-v99m-7h5j 7.2

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege)...

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Record
GHSA-vgpj-v99m-7h5j
CVSS 4.0
7.2 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:L/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
CVSS 3.1
7.6 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Weakness
CWE-285
Updated
2026-11-02
NVD 7.2

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Record
CVE-2026-79667
CVSS 4.0
7.2 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:L/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
CVSS 3.1
7.6 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Weakness
CWE-285
Updated
2026-11-02
OSV 7.2

Ech0 before 4.4.3 Authentication Bypass via Scope Enforcement

Ech0 version 4.3.4 and earlier fails to reliably enforce scoped access token (least-privilege) restrictions on several privileged admin routes. Multiple privileged endpoints (e.g., /api/inbox, /api/panel/comments, /api/backup/export) omit scope checks and authorize based only on the user's admin role, and the backup export handler discards token scope metadata entirely. An attacker holding a deliberately limited (low-scope) admin access token can reach broader privileged functionality than intended, including reading the inbox and exporting a full database backup ZIP archive. Fixed in 4.4.3.

Record
CVE-2026-79667
CVSS 4.0
7.2 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-285
Updated
2026-11-02
OSVGHSA-4h9q-p5j4-xvvh 7.6

Ech0: Scoped admin access tokens can bypass least-privilege controls on privileged endpoints, including backup export

Summary

Ech0 scoped access tokens do not reliably enforce least privilege: multiple privileged admin routes omit scope checks, and the backup export handler strips token scope metadata entirely, allowing a low-scope admin access token to reach broader admin functionality than intended.

Impact

An attacker who obtains a deliberately limited access token for an admin account can use that token to access privileged functionality outside its assigned scope. Confirmed impact includes access to /api/inbox with a token scoped only for echo:read and successful backup export via /api/backup/export?token=..., which returns a full ZIP archive. In practice, this turns a narrowly delegated API token into a broader privileged access and data exfiltration primitive.

Details

The issue is caused by a split authorization model:

  • JWTAuthMiddleware() authenticates the token and stores scope metadata in the viewer context
  • RequireScopes(...) enforces least privilege, but only when a route explicitly adds it
  • several privileged routes omit RequireScopes(...)
  • multiple service methods then authorize using only user.IsAdmin

internal/middleware/scope.go shows that scope enforcement is opt-in:

func RequireScopes(scopes ...string) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		v := viewer.MustFromContext(ctx.Request.Context())
		if v.TokenType() == authModel.TokenTypeSession {
			ctx.Next()
			return
		}
		if v.TokenType() != authModel.TokenTypeAccess { ... }
		if !containsValidAudience(v.Audience()) { ... }
		if !containsAllScopes(v.Scopes(), scopes) { ... }
		ctx.Next()
	}
}

Representative privileged routes omit RequireScopes(...), for example internal/router/inbox.go:

func setupInboxRoutes(appRouterGroup *AppRouterGroup, h *handler.Bundle) {
	appRouterGroup.AuthRouterGroup.GET("/inbox", h.InboxHandler.GetInboxList())
	appRouterGroup.AuthRouterGroup.GET("/inbox/unread", h.InboxHandler.GetUnreadInbox())
	appRouterGroup.AuthRouterGroup.PUT("/inbox/:id/read", h.InboxHandler.MarkInboxAsRead())
	appRouterGroup.AuthRouterGroup.DELETE("/inbox/:id", h.InboxHandler.DeleteInbox())
	appRouterGroup.AuthRouterGroup.DELETE("/inbox", h.InboxHandler.ClearInbox())
}

Other source-confirmed unguarded privileged surfaces include:

  • /api/panel/comments*
  • /api/addConnect
  • /api/delConnect/:id
  • /api/migration/*
  • /api/backup/export

Service-layer authorization often checks only admin role. For example, internal/service/inbox/inbox.go:

func (inboxService *InboxService) ensureAdmin(ctx context.Context) error {
	userid := viewer.MustFromContext(ctx).UserID()
	user, err := inboxService.commonService.CommonGetUserByUserId(ctx, userid)
	if err != nil {
		return err
	}
	if !user.IsAdmin {
		return errors.New(commonModel.NO_PERMISSION_DENIED)
	}
	return nil
}

The backup export path is a stronger variant because it discards token metadata before authorization. internal/handler/backup/backup.go reparses a query token and rebuilds a bare viewer from only the user ID:

func (backupHandler *BackupHandler) ExportBackup() gin.HandlerFunc {
	return res.Execute(func(ctx *gin.Context) res.Response {
		token := ctx.Query("token")
		claims, err := jwtUtil.ParseToken(token)
		if err != nil { ... }

		reqCtx := viewer.WithContext(context.Background(), viewer.NewUserViewer(claims.Userid))
		if err := backupHandler.backupService.ExportBackup(ctx, reqCtx); err != nil { ... }
		return res.Response{Msg: commonModel.EXPORT_BACKUP_SUCCESS}
	})
}

This drops token type, scopes, audience, and token ID before the backup service runs.

Proof of concept

1. Start the app

docker run -d \
  --name ech0 \
  -p 6277:6277 \
  -v /opt/ech0/data:/app/data \
  -e JWT_SECRET="Hello Echos" \
  sn0wl1n/ech0:latest

2. Initialize an owner account

curl -sS -X POST "http://127.0.0.1:6277/api/init/owner" \
  -H 'Content-Type: application/json' \
  -d…
Record
GHSA-4h9q-p5j4-xvvh
CVSS 3.1
7.6 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Weakness
CWE-285
Updated
2026-11-02
OSVGO-2026-5123 No score

Ech0: Scoped admin access tokens can bypass least-privilege controls on privileged endpoints, including backup export in github.com/lin-snow/ech0

Ech0: Scoped admin access tokens can bypass least-privilege controls on privileged endpoints, including backup export in github.com/lin-snow/ech0.

NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.

(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)

The additional affected modules and versions are: github.com/lin-snow/ech0 before v4.3.5.

Record
GO-2026-5123
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/lin-snow/ech0
Go
before 4.3.5
4.3.5
github.com/lin-snow/ech0
Go
All versions None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-79667 is a high vulnerability (CVSS 7.2) in Lin-snow Ech0, published April 10, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.32%, the 25th percentile. Fixed in github.com/lin-snow/ech0 4.3.5.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open