UNPKG

harden-react-markdown-urls

Version:

πŸ›‘οΈ Secure wrapper for react-markdown that sanitizes link and image URLs using rehype-harden-urls. Do complex things, the simple way.

163 lines (108 loc) β€’ 7.69 kB
# harden-react-markdown-urls πŸ”—πŸ”’<img src="https://raw.githubusercontent.com/mayank1513/mayank1513/main/popper.png" style="height: 40px"/> [![test](https://github.com/tiny-md/harden-urls/actions/workflows/test.yml/badge.svg)](https://github.com/tiny-md/harden-urls/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/tiny-md/harden-urls/graph/badge.svg?flag=harden-react-markdown-urls)](https://codecov.io/gh/tiny-md/harden-urls) [![Version](https://img.shields.io/npm/v/harden-react-markdown-urls.svg?colorB=green)](https://www.npmjs.com/package/harden-react-markdown-urls) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/d18m/harden-react-markdown-urls.svg)](https://www.npmjs.com/package/harden-react-markdown-urls) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/harden-react-markdown-urls) [![NPM License](https://img.shields.io/npm/l/harden-react-markdown-urls)](../../LICENSE) <p align="center"> <img src="./harden-react-markdown.jpg" alt="harden-react-markdown-urls banner: Secure your Markdown links and images" /> </p> πŸ›‘οΈ A **drop-in security wrapper (Higher-Order Component)** for [`react-markdown`](https://github.com/remarkjs/react-markdown) that automatically sanitizes URLs in your rendered content using the deep cleaning capabilities of [`rehype-harden-urls`](https://github.com/tiny-md/harden-urls/tree/main/libs/harden-urls). > β€œDo complex things, the simple way.” --- ## ✨ Features - **Full URL Hardening**: Protects against malicious links and tracking parameters (like `utm_`, `fbclid`) using robust normalization and strict protocol checking. - **Drop-in Integration**: Wraps any `react-markdown` instance with zero configuration required. - **Seamless Compatibility**: Works perfectly alongside existing `rehypePlugins`. - **Flexible Policies**: Fully leverages `rehype-harden-urls` presets (`strict`, `balanced`, `relaxed`) and granular custom options. - **Lightweight**: Pure functional HOC with minimal overhead. --- ## πŸ“¦ Installation We recommend using utilities such as `toRegexps`, `domainsToRegexps`, etc. from `harden-urls` package for creating your custom configurations. ```bash pnpm add harden-react-markdown-urls harden-urls ``` **_or_** ```bash npm install harden-react-markdown-urls harden-urls ``` --- ## 🧠 Usage ### Basic Setup Wrap your base `ReactMarkdown` component with `hardenReactMarkdown` and provide your default security preset. ```tsx import ReactMarkdown from "react-markdown"; import { hardenReactMarkdown } from "harden-react-markdown-urls"; import { presets } from "harden-urls/utils"; // 1. Define your default policy (e.g., balanced is a great default) const HardenedMarkdown = hardenReactMarkdown(ReactMarkdown, presets.balanced); // 2. Use the wrapped component function MyComponent({ markdownText }) { return <HardenedMarkdown>{markdownText}</HardenedMarkdown>; } ``` πŸ‘‰ **Gotcha:** Any unsafe link (e.g., `[Click me](javascript:alert('xss'))`) will have its `href` attribute removed or be pruned, based on the policy. ### Fine-grained Control & Overrides Use the `hardenedOptions` prop to override the default policy for a specific instance. This is useful for content sources with different security requirements. ```tsx <HardenedMarkdown // Override the default 'balanced' policy for this instance hardenedOptions={{ link: { allowedProtocols: new Set(["https:", "mailto:"]) }, image: { allowedProtocols: new Set(["https:"]) }, // Use the callback to log any blocked URLs onUnsafeUrl: (url, node, type) => console.warn("Blocked:", type, url), }}> {markdownText} </HardenedMarkdown> ``` --- ## βš™οΈ Props | Prop | Type | Description | | -------------------------- | ------------------------- | ------------------------------------------------------------------------------------- | | `hardenedOptions` | `RehypeHardenUrlsOptions` | **Instance-level override** for the hardening policy defined by `rehype-harden-urls`. | | All `react-markdown` props | – | Fully supported and forwarded to the wrapped component. | --- ## ⚠️ Best Practice: The Security Stack For maximum safety when dealing with **untrusted Markdown that contains embedded HTML** (i.e., when you use `rehype-raw`), you must pair this package with `rehype-sanitize`. The recommended secure chain is: 1. **`rehype-raw`**: Parses raw HTML into the tree. 2. **`rehype-harden-urls`** (via this package): Deeply cleans and normalizes all URL **values**. 3. **`rehype-sanitize`**: Provides the final structural guardrail, removing any forbidden tags or attributes. **Always ensure** your `react-markdown` component allows for both `rehype-harden-urls` and a general sanitizer: ```tsx // Example of a minimal safe component const SafeMarkdown = hardenReactMarkdown(ReactMarkdown, presets.balanced, { rehypePlugins: [rehypeRaw, rehypeSanitize], // Ensure sanitization is always on top }); ``` --- ## βš–οΈ Why Use This Over Basic Sanitizers? This package closes critical security gaps often missed by simpler solutions, including Vercel Labs’ older efforts. | Capability | harden-react-markdown-urls | Vercel Labs' Simple Sanitizers | | :----------------------------------------------------- | :------------------------------ | :----------------------------- | | **Deep URL Cleaning** (Normalization, Case-folding) | βœ… | ❌ | | **Strip Tracking Parameters** (`utm_`, `fbclid`, etc.) | βœ… | ❌ | | **Hardens Embedded HTML URLs** (via `rehype-raw`) | βœ… (Requires `rehype-sanitize`) | ⚠️ Incomplete | | **Protocol Validation** | βœ… Comprehensive | ⚠️ Basic Prefix Check | --- ## πŸ“š Security Presets This package utilizes the following presets from `rehype-harden-urls` for quick configuration: | Preset | Description | Key Protocols Allowed | | :--------- | :------------------------------------------------ | :------------------------------------ | | `strict` | HTTPS-only, strips all known trackers | `https:` | | `balanced` | Safe default: allows mailto and secure protocols | `https:`, `mailto:` | | `relaxed` | Allows insecure HTTP, minimal parameter stripping | `http:`, `https:`, `mailto:`, `data:` | --- ## 🀝 Contribution & Support We enthusiastically welcome contributions from the community! Whether you are reporting a bug, suggesting a new feature, or submitting a pull request, your help makes this a safer tool for everyone. Please check the [GitHub Issues](https://github.com/tiny-md/harden-urls/issues) for open tasks. **πŸ’– Adopt and Support:** If this package helps secure your application, consider giving us a star on GitHub! You can also [sponsor our work](https://github.com/sponsors/mayank1513) to help fund continued development and maintenance. --- ## πŸͺ· License This project is licensed under the **MIT License**. MIT Β© [Mayank Chaudhari](https://github.com/mayank1513) > We express gratitude to **react-markdown**, **rehype**, and **Vercel Labs** for the inspiration. --- <p align="center" style="text-align:center">with πŸ’– by <a href="https://mayank-chaudhari.vercel.app" target="_blank">Mayank Kumar Chaudhari</a></p>