Skip to content

Unsafe Markdown Rendering Leading to Potential Injection via Unfiltered URL Schemes

Moderate
mattwoberts published GHSA-wm2w-gfh7-qg69 Jul 3, 2026

Package

gomod getfider/fider (Go)

Affected versions

< 0.34.0

Patched versions

0.34.0

Description

Overview

This report identifies a security weakness in the Fider application where backend markdown rendering does not sanitize or validate URL schemes. As a result, unsafe schemes such as javascript: can be embedded into generated HTML content and propagated through secondary channels such as RSS feeds and email templates.

While this does not result in a reliably exploitable cross-site scripting (XSS) vulnerability in modern environments, it introduces inconsistent security controls and may become exploitable under specific client conditions.


Affected Components

  • app/pkg/markdown/markdown.go
  • app/pkg/tpl/funcs.go
  • app/handlers/feed.go
  • views/email/*.html

Technical Details

1. Unsafe Markdown Rendering

func Full(input string, handleImages bool) template.HTML {
    output := markdown.ToHTML([]byte(input), parser, renderer)
    return template.HTML(strings.TrimSpace(string(output)))
}
  • Markdown is converted to HTML
  • Output is directly cast to template.HTML
  • No sanitization or URL scheme validation is applied

2. Template Rendering

"markdown": func(input string) template.HTML {
    return markdown.Full(input, true)
}
  • Unsafe output is propagated into templates

3. Email Template Injection

{{ .content }}
  • Raw HTML is rendered without escaping or sanitization

4. RSS Feed Rendering

return string(markdown.Full(title + post.Description + footer, true))
  • Unsafe HTML is embedded directly into RSS XML content

Proof of Concept

Payload

[Click here](javascript:alert('XSS-POC'))

Backend Output

<p><a href="javascript:alert(" rel="nofollow noreferrer" title="XSS-POC">Click here</a>)</p>

This confirms that unsafe URL schemes are preserved in the output.


Data Flow

User Input → Markdown Parser → HTML Conversion → template.HTML → Email/RSS Output

No sanitization step is applied in this pipeline.


Reproduction Steps

  1. Deploy Fider locally
  2. Create a new post with the following content:
    [Click here](javascript:alert('XSS-POC'))
    
  3. Access:
    • RSS feed: /feed/global.atom
    • Trigger email notification
  4. Observe that the generated HTML contains javascript: URLs

Execution Analysis

Context Behavior
Web UI Protected via DOMPurify
Email Dependent on client filtering
RSS Dependent on reader behavior

Key Observations

  • No automatic script execution observed
  • Requires user interaction (click)
  • Modern clients mitigate execution
  • Potential exposure exists in less secure environments

Impact

Direct Impact

  • Unsafe links included in:
    • Email notifications
    • RSS feeds

Indirect Risk

  • Social engineering vector
  • Potential exploitation in:
    • Legacy email clients
    • Custom RSS readers
    • Intranet environments

Security Concerns

  • Lack of backend sanitization
  • Inconsistent security model
  • Violation of defense-in-depth principles

Risk Assessment

Factor Evaluation
Exploitability Limited
User Interaction Required
Client Dependency High
Web UI Exposure None
Consistency Weak

Remediation

Recommended Fix

Apply HTML sanitization using bluemonday:

import "github.com/microcosm-cc/bluemonday"

policy := bluemonday.UGCPolicy()
safe := policy.Sanitize(string(output))
return template.HTML(safe)

Additional Recommendations

  • Explicitly block unsafe schemes (javascript:, data:)
  • Align backend sanitization with frontend DOMPurify logic
  • Add centralized output encoding policy

Conclusion

This issue represents a backend sanitization gap that allows unsafe URL schemes to persist in rendered output. Although not directly exploitable as XSS in modern environments, it introduces a security inconsistency and potential risk in less protected contexts.

Given these factors, this issue is best classified as Medium severity in context-dependent scenarios.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N

CVE ID

No known CVE

Weaknesses

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. Learn more on MITRE.

Improper Encoding or Escaping of Output

The product prepares a structured message for communication with another component, but encoding or escaping of the data is either missing or done incorrectly. As a result, the intended structure of the message is not preserved. Learn more on MITRE.

Credits