CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-FPW6-HRG5-Q5X5

GHSA-FPW6-HRG5-Q5X5: Irrevocable Access Tokens and Nil-Pointer Dereference in Ech0

Amit Schendel
Amit Schendel
Senior Security Researcher

May 8, 2026·7 min read·182 visits

Executive Summary (TL;DR)

A missing expiration claim in Ech0's 'never expire' JWTs causes panics and silently breaks token revocation, allowing attackers to maintain perpetual access with stolen tokens.

Ech0 access tokens created with the 'never expire' option generate JSON Web Tokens (JWT) missing the 'exp' claim. This structural omission causes a nil-pointer dereference during logout and prevents the JTI blacklisting mechanism from functioning. Consequently, leaked access tokens cannot be revoked by administrators.

Vulnerability Overview

Ech0 is an open-source, self-hosted publishing platform that provides token-based authentication for API and CLI integrations. Users generate these access tokens via the administration interface and can configure them to "never expire" based on integration requirements. The platform utilizes stateless JSON Web Tokens (JWT) to track and manage these authenticated sessions across application endpoints.

When a user selects the "never expire" option, the application issues a JWT that completely omits the standard exp (expiration) claim. This specific structural choice creates immediate compatibility issues with the platform's internal security controls. The underlying vulnerability maps to CWE-613 (Insufficient Session Expiration), CWE-476 (NULL Pointer Dereference), and CWE-300 (Lack of Revocation for Stolen Credentials).

The flaw manifests concurrently across multiple components of the Ech0 architecture. The absence of the expiration claim breaks the logic responsible for calculating remaining token validity, causing runtime panics during logout procedures. Simultaneously, the token revocation mechanism fails entirely, allowing an attacker who compromises a "never expire" token to maintain perpetual system access.

Root Cause Analysis

The root cause is a fundamental disconnect between stateless JWT mechanics and the system's token blacklisting implementation. The application relies on a JTI (JWT ID) blacklist to revoke active tokens before their natural expiration date. The repository method RevokeToken explicitly requires a positive remaining Time-to-Live (TTL) integer to store the JTI in the caching layer.

During a standard logout event, the handler located at internal/handler/auth/auth.go intercepts the JWT and extracts the ExpiresAt data structure. The application attempts to calculate the remaining TTL by evaluating time.Until(claims.ExpiresAt.Time). Because the exp claim is strictly absent from "never expire" tokens, the ExpiresAt pointer evaluates directly to nil.

Dereferencing this nil pointer triggers a fatal HTTP 500 panic within the Go runtime environment. Even if the panic is artificially suppressed, the resulting TTL calculation yields a zero or negative duration. The RevokeToken function contains a guard clause that silently discards any revocation request where remainTTL <= 0, ensuring the JTI is never populated into the blacklist.

Furthermore, the administrative token deletion interface operates independently of the JWT validation layer. When an administrator deletes an access token via the user interface, the application drops the token metadata from the relational database. It fails to extract the underlying JTI and propagate it to the revocation service, leaving the cryptographically valid JWT fully operational.

Code Analysis

The vulnerability exists across both the token issuance and revocation code paths. The vulnerable token generation logic omitted the ExpiresAt field entirely when a user requested an indefinite lifespan. The patch at commit eab62379c795c3f4850a9ca938ae3f27d7171541 resolves this by injecting a fixed 100-year fallback duration for these specific tokens.

The following code segment illustrates the correction applied within the CreateAccessClaimsWithExpiry function. The developer established a constant neverExpiryFallback and enforces it when the requested expiry evaluates to zero or less.

// PATCH: Assign a 100-year fallback instead of omitting the claim
const neverExpiryFallback = int64(100 * 365 * 24 * 3600)
if expiry <= 0 {
    expiry = neverExpiryFallback
}

To prevent panics from legacy tokens already in circulation, the patch introduces a safe parsing mechanism. The remainingTTLFromClaims function verifies the pointer status before attempting the dereference operation. If ExpiresAt evaluates to nil, it assumes the legacy 100-year fallback duration, allowing the revocation process to continue safely.

// PATCH: Safely calculate TTL without panicking on nil pointers
func remainingTTLFromClaims(expiresAt *jwt.NumericDate) time.Duration {
    const legacyNeverFallback = 100 * 365 * 24 * time.Hour
    if expiresAt == nil {
        return legacyNeverFallback
    }
    return time.Until(expiresAt.Time)
}

The administrative deletion gap was independently addressed by modifying the DeleteAccessToken service logic. The updated code now queries the database for the token's specific JTI prior to executing the deletion command. It subsequently invokes the RevokeToken service explicitly, ensuring the stateless JWT is properly blacklisted alongside the database record removal.

Exploitation Methodology

Exploitation of this vulnerability strictly requires the attacker to first obtain a valid "never expire" access token. These tokens are commonly deployed in CI/CD pipelines, hardcoded into configuration files, or embedded in external integration scripts. If an attacker compromises a developer's local environment or uncovers a hardcoded secret in a source repository, they gain the prerequisite cryptographic material.

Once the token is acquired, the attacker authenticates to the Ech0 API using standard Bearer authorization headers. The platform validates the JWT cryptographic signature successfully, ignoring the missing expiration claim. The attacker can then interact with the system using the full operational privileges defined by the compromised token's scopes.

If the administrator detects the anomalous activity, they typically attempt to terminate the session via the Ech0 administration panel. The user interface successfully reflects that the token is deleted. However, because the system fundamentally fails to blacklist the JTI, the attacker's subsequent API requests continue to authenticate without interruption.

A Python-based proof of concept explicitly confirms this revocation failure. The script generates a "never expire" token, issues an API request to verify functional access, and triggers the administrative deletion endpoint. A final API request using the deleted token returns an HTTP 200 OK response, demonstrating the complete failure of the revocation mechanism.

Impact Assessment

The primary impact of this vulnerability is the persistent, unmitigated authorization of compromised credentials. Stateless authentication mechanisms require robust JTI blacklisting to handle premature token invalidation effectively. By bypassing this specific control, the vulnerability grants attackers permanent access to the affected Ech0 instance.

The CVSS v3.1 base score for this vulnerability is calculated at 7.4 (High). The vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N correctly reflects high confidentiality and integrity impacts. The attack complexity is marked as high because the vulnerability itself does not grant initial access; it strictly prevents the termination of an existing, stolen session.

The nil-pointer dereference introduces a secondary, highly localized availability impact. Authenticated users attempting to interact with specific endpoints that trigger the TTL calculation experience localized HTTP 500 errors. However, this panic does not crash the broader Go application service, limiting the overall denial-of-service capability against the platform.

The fix implemented in the patch completely mitigates both the nil-pointer dereference and the logic bypass. By establishing a hardcoded 100-year limit and bridging the gap between database deletion and JWT revocation, the application successfully restores administrative control over session lifecycles.

Remediation and Mitigation

The vendor addressed the vulnerability in commit eab62379c795c3f4850a9ca938ae3f27d7171541. Administrators must upgrade their Ech0 instances to version 1.4.8 or later to apply the patched token generation and revocation logic. This specific update automatically handles legacy tokens gracefully via the newly introduced remainingTTLFromClaims helper function.

If an immediate update is functionally unfeasible, administrators can execute a global secret rotation to invalidate all existing tokens. By modifying the JWT_SECRET variable in the core application configuration, the server will reject all current cryptographic signatures. This action requires all legitimate users and automated systems to re-authenticate and provision entirely new access tokens.

Security teams should actively monitor application logs for unexpected HTTP 500 errors originating specifically from the /api/auth/logout endpoint. These errors serve as a high-fidelity indicator that a system process or user is attempting to invalidate a legacy token. Database administrators can simultaneously audit the access_token_settings table for active tokens configured with an empty or never expiry value.

Developers implementing JWT authentication workflows should ensure that the exp claim is consistently populated, even for heavily extended sessions. Establishing a maximum realistic bound, such as the 100-year fallback utilized in the Ech0 patch, maintains structural consistency while fulfilling the functional requirement of non-expiring credentials.

Official Patches

lin-snowOfficial fix commit in the Ech0 repository
GitHubRepository Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
7.4/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

Affected Systems

Ech0 (all versions prior to commit eab62379)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Ech0
lin-snow
< 1.4.81.4.8
AttributeDetail
CWE IDCWE-613, CWE-476, CWE-300
Attack VectorNetwork
CVSS Score7.4
ImpactPersistent Authorization Bypass
Exploit StatusProof of Concept
ComponentJWT Handler & Authentication Repository

MITRE ATT&CK Mapping

T1528Steal Application Access Token
Credential Access
T1078Valid Accounts
Defense Evasion
CWE-613
Insufficient Session Expiration

The application does not properly enforce expiration or revocation of session tokens, allowing an attacker to reuse a captured token indefinitely.

Vulnerability Timeline

Fix commit pushed to the repository
2026-05-03
GHSA-FPW6-HRG5-Q5X5 published in the GitHub Advisory Database
2026-05-07

References & Sources

  • [1]GitHub Advisory Database
  • [2]OSV Data Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•40 minutes ago•CVE-2026-72802
6.9

CVE-2026-72802: Sensitive Information Disclosure via Administrative Asset Resolvers in SiYuan Note

SiYuan Note versions prior to v3.7.4 contain an information disclosure vulnerability in the `/api/asset/resolveAssetPath` endpoint. This endpoint returns absolute backend filesystem paths unmodified to CheckAuth-only requests. Low-privileged users or unauthenticated readers under publish mode can exploit this to leak the local directory layout, operating system username, and overall host deployment structure.

Amit Schendel
Amit Schendel
0 views•6 min read
•about 2 hours ago•CVE-2026-72801
8.7

CVE-2026-72801: Information Disclosure of Cryptographic Key Material in SiYuan

An access control vulnerability in the SiYuan personal knowledge management platform before version v3.7.4 exposes notebook encryption parameters to unauthenticated remote attackers. When the platform is configured in Publish Mode, specific API endpoints fail to enforce authorization checks. This access failure leaks key-derivation materials, password verifiers, and wrapped database keys to anonymous network clients.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 4 hours ago•CVE-2026-72800
5.8

CVE-2026-72800: Missing Authorization in SiYuan Personal Knowledge Management System

A security vulnerability in the SiYuan local-first personal knowledge management system allows unauthenticated remote attackers to bypass logical boundary controls in publish (read-only) mode. By interacting with endpoints that lack proper publish-access validation, an attacker can disclose the application's internal database schemas and harvest block IDs across both public and private notebooks. This metadata leakage compromises the confidentiality of restricted documents and provides foundational information for targeted extraction.

Alon Barad
Alon Barad
2 views•5 min read
•about 5 hours ago•CVE-2026-72803
6.9

CVE-2026-72803: Information Disclosure via Missing Authorization in SiYuan API

An information disclosure vulnerability exists in the SiYuan personal knowledge management system versions prior to v3.7.4. The application fails to enforce publish-access filters on block attribute retrieval endpoints. Consequently, unauthenticated remote attackers can bypass document-level protection rules (such as password protection or disabled-publish flags) to retrieve sensitive block-level attributes, including aliases, memos, block names, and custom metadata fields, by querying the API using guessed or known block IDs.

Alon Barad
Alon Barad
4 views•7 min read
•about 6 hours ago•GHSA-7J72-F6WG-CXW6
8.6

CVE-2026-68584: Authentication Bypass via Auxiliary Content Endpoints in SiYuan

An authentication bypass vulnerability (classified as CWE-288) exists in the publish-mode component of SiYuan, a Go-based note-taking application. This security flaw allows unauthenticated remote attackers to bypass password-protected note boundaries by leveraging auxiliary block endpoints that fail to enforce document access checks. Attackers can exploit this issue by first harvesting document metadata via a public search endpoint and subsequently fetching full rendered document contents using vulnerable block endpoints. This technical analysis explores the root cause, exploitation methodology, and remediation path.

Alon Barad
Alon Barad
2 views•7 min read
•about 7 hours ago•CVE-2026-77465
7.5

CVE-2026-77465: Uncontrolled Recursion in toml-node Deserializer Leads to Denial of Service

An uncontrolled recursion vulnerability (CWE-674) in the toml-node NPM package (published as toml) prior to version 4.2.0 allows unauthenticated remote attackers to trigger process-wide Denial of Service (DoS) crashes. By submitting TOML payloads with deep bracket or brace nesting, attackers exhaust the V8 runtime stack limit.

Amit Schendel
Amit Schendel
6 views•6 min read