Back to Blog
critical SEVERITY4 min read

Tung Tung Tracker Admin API: Missing Authentication in `/api/sync`

The Tung Tung Tracker administrative API endpoints (`/api/sync`, `/api/backfill`, `/api/show`, `/api/overlay/hide`) relied solely on localhost origin and a static `X-Tracker` header for protection, allowing any local process to execute privileged operations. The fix introduces proper session-based authentication and a random IPC secret for desktop-to-server communication.

O
By Orbis AppSec
•Published September 29, 2026•Reviewed September 29, 2026

Answer Summary

The Tung Tung Tracker's administrative API endpoints (`/api/sync`, `/api/backfill`, `/api/show`, `/api/overlay/hide`) in first-party code lacked authentication beyond localhost origin checking and a static header. Any local process could trigger data synchronization, backfill operations, or overlay visibility changes. The fix replaces the static `X-Tracker` header with session-based authentication and a per-instance IPC secret passed via `app.config["IPC_SECRET"]`. CWE-287 (Improper Authentication).

Vulnerability at a Glance

cweCWE-287
fixSession-based auth with random IPC secret for desktop-to-server calls
riskLocal privilege escalation allowing any process to trigger administrative operations
languagePython
root causeAdministrative endpoints validated only localhost origin and static header, not user identity
vulnerabilityAuthentication Bypass

Affected Versions

Affected not applicable (first-party code)
Fixed in commit-based fix (see PR)
Ecosystem N/A
CVE / GHSA not assigned
CWE CWE-287 (Improper Authentication)

Introduction

The Tung Tung Tracker's administrative API endpoints—responsible for data synchronization, backfill operations, and overlay visibility—sat exposed behind only two weak controls: a localhost origin check and a static X-Tracker: 1 HTTP header. The guard() function in the request handler performed no user identity validation, meaning any process running on the local machine could trigger privileged operations by simply knowing the header value.

This is a textbook CWE-287 vulnerability: authentication that verifies something other than the claimed identity. Origin validation proves where a request came from, not who made it. The static header added no meaningful barrier—it's a secret shared with every local process by default.

The Vulnerability Explained

The vulnerable code relied on exception-based handling for expired tokens in JWT decoding, but more critically, the administrative endpoints bypassed meaningful authentication entirely:

# Before: guard() only checked localhost and static header
def test_post_requires_custom_header(client):
    assert client.post("/api/sync").status_code == 403
    assert client.post("/api/sync", headers={"X-Tracker": "1"}).status_code == 200

The test itself documented the vulnerability: presenting X-Tracker: 1 was sufficient to access /api/sync, /api/backfill, /api/show, and /api/overlay/hide. No session, no user identity, no per-instance secret.

Attack scenario: A malicious local process—perhaps a compromised npm package or a rogue browser extension with local access—iterates through ports 8000-9000, sends POST /api/sync with X-Tracker: 1, and triggers data synchronization against the user's intent. The same applies to backfill operations (potentially expensive) or overlay manipulation (UI disruption).

The make_server("127.0.0.1", port, app, threaded=True) binding meant the API was intentionally local-only, but "local" in modern systems includes sandboxed apps, containerized services, and browser extensions—all of which share the localhost interface.

The Fix

The fix introduces two complementary authentication mechanisms:

1. Session-based authentication for web clients

The X-Tracker header check is removed. Instead, loading pages like / or /overlay establishes a Flask session cookie, which subsequent mutating requests must present:

# After: session established by page load, no static header needed
def test_post_requires_custom_header(client):
    assert client.post("/api/sync").status_code == 403
    client.get("/")  # loading our own page grants the session
    assert client.post("/api/sync").status_code == 200

2. IPC secret for desktop-to-server communication

The desktop application cannot use session cookies (it calls from a native process), so it receives a random secret passed through app.config["IPC_SECRET"]:

# app.py change
-    instance.publish(port)
+    instance.publish(port, app.config["IPC_SECRET"])

The desktop client presents this token on self-wake calls, proven by a dedicated test:

def test_show_requires_ipc_token(tmp_path):
    """The desktop app's self-wake call has no session, so it must present the random IPC token."""

This bifurcated design elegantly solves both use cases: web clients get standard session cookies, while the native desktop client gets a cryptographically random, per-instance secret that expires with the process.

Key Takeaways

  • Static headers are not authentication: The X-Tracker: 1 header provided only security theater—any local process could discover and replay it.
  • Origin validation ≠ identity validation: 127.0.0.1 checks prevent remote attacks but not local privilege escalation between processes.
  • Different clients need different authentication: The fix recognizes that browser-based and native-desktop clients have different capabilities, providing session cookies for the former and IPC tokens for the latter.
  • Tests document vulnerabilities: The original test_post_requires_custom_header explicitly encoded the vulnerable behavior; security review of test suites can reveal assumed trust boundaries.

How Orbis AppSec Detected This

  • Source: HTTP request parameters and headers reaching the administrative endpoint handlers
  • Sink: The guard() function's authorization check, which validated only request.remote_addr and the static X-Tracker header
  • Missing control: No session validation, token binding to user identity, or per-instance secret verification before executing privileged operations
  • CWE: CWE-287 — Improper Authentication
  • Fix: Replaced static header with session-based authentication for web clients and random IPC secret for desktop process communication

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

The Tung Tung Tracker fix demonstrates that local-only APIs require the same rigor as remote-facing ones. The X-Tracker header created a false sense of security while offering no meaningful protection against local threats. By replacing it with proper session management and per-instance IPC secrets, the fix closes the authentication gap without breaking the desktop integration that makes the application useful.

Prevention and further reading

Frequently Asked Questions

Why does the desktop app need a separate IPC token instead of using the same session cookie as the web interface?

The desktop app's self-wake call originates from a native process without a browser session, so it cannot present a session cookie. The fix generates a random `IPC_SECRET` passed to `instance.publish()` that the desktop client presents as proof of local ownership.

Does loading `/overlay` or `/` still grant administrative privileges to subsequent requests?

Yes, but now legitimately—the fix changes the test to show that loading these pages establishes a session cookie, which mutating requests must present. Previously, the static `X-Tracker: 1` header alone was sufficient for any request.

Which administrative endpoints were affected by the missing authentication in `make_server`?

`/api/sync` triggers data synchronization, `/api/backfill` runs data backfill operations, `/api/show` displays the overlay, and `/api/overlay/hide` hides it—all four lacked authentication beyond localhost origin checks.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #18

Related Articles

critical

POST /api/generate Lacks Authentication, Allowing Unauthenticated

A resume generation endpoint in a Node.js backend accepted requests from any caller with network access, allowing attackers to consume OpenAI API quota without restriction. The vulnerability stemmed from missing authentication middleware on a cost-bearing endpoint. The fix adds mandatory API key validation via HTTP headers before processing any generation requests.

critical

chrome.runtime.onMessage: Missing Sender Validation in Extension

A critical authentication flaw in a Chrome extension's message handling allowed arbitrary extensions and malicious web pages to trigger sensitive operations including script injection and tab manipulation. The vulnerability existed because chrome.runtime.onMessage listeners processed requests without verifying sender identity or origin, trusting any message source by default.

critical

Google Generative AI Keys Exposed in Client-Side Fetch URLs

A client-side AI model discovery utility was embedding Google Generative AI API keys directly in fetch request URLs, making them visible to any user inspecting network traffic or browser DevTools. The fix moves the key from the URL query parameter to a secure HTTP header, eliminating exposure while maintaining API authentication.

critical

boardroom Server Handler Missing Authentication on HTTP Endpoints

The boardroom server's `Handler` class, extending `SimpleHTTPRequestHandler`, exposed sensitive HTTP endpoints without any caller authentication. An attacker could exploit this by making cross-origin requests to internal ports through DNS rebinding, accessing `/alerts.json`, `/dismiss`, and `/events.js` without authorization. The fix adds `is_local_origin()` checks to both `do_GET()` and `do_POST()` methods.

critical

docker_rpc.uc Command Injection: Unsanitized RPC Parameters

A critical command injection vulnerability in the Docker RPC handler allowed authenticated attackers to execute arbitrary system commands by injecting shell metacharacters into container ID, port, user ID, or command parameters. The fix validates all user-supplied inputs against strict whitelist patterns before interpolating them into shell commands.

critical

SGX Enclave ecall_store_data memcpy Buffer Overflow in 256-Byte

The Intel SGX enclave's trusted bridge functions `ecall_store_data` and `ecall_retrieve_data` used `memcpy()` to move data into and out of a fixed 256-byte `secure_storage` buffer without validating that `data_len` fit within destination boundaries. An attacker providing oversized `data_len` values could corrupt enclave memory, breaking SGX's confidentiality guarantees.