惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
F
Fortinet All Blogs
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
博客园 - 司徒正美
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
PCI Perspectives
PCI Perspectives
N
News | PayPal Newsroom
aimingoo的专栏
aimingoo的专栏
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
N
News and Events Feed by Topic
O
OpenAI News
博客园 - Franky
M
MIT News - Artificial intelligence
H
Heimdal Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
L
LINUX DO - 热门话题
Know Your Adversary
Know Your Adversary
S
Security @ Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Hacker News: Front Page
TaoSecurity Blog
TaoSecurity Blog
The Cloudflare Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
MongoDB | Blog
MongoDB | Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LangChain Blog
人人都是产品经理
人人都是产品经理
C
CERT Recently Published Vulnerability Notes
Google DeepMind News
Google DeepMind News
罗磊的独立博客
博客园 - 【当耐特】
C
Cisco Blogs
K
Kaspersky official blog
Cisco Talos Blog
Cisco Talos Blog
IT之家
IT之家
Recent Announcements
Recent Announcements
Cyberwarzone
Cyberwarzone
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
Y
Y Combinator Blog
AI
AI
爱范儿
爱范儿
S
Schneier on Security
Google DeepMind News
Google DeepMind News

Streamdown Documentation

Configuration FAQ Getting Started Introduction Security Animation Carets Code Blocks Components GitHub Flavored Markdown Interactivity Internationalization Memoization Migrate from react-markdown Styling Unterminated Block Parsing Typography Usage @streamdown/cjk @streamdown/code Built-in Plugins @streamdown/math @streamdown/mermaid Custom renderers
Link Safety
Vercel · 2026-04-11 · via Streamdown Documentation

Configurable confirmation modal for external links to protect users from malicious URLs.

When rendering AI-generated or user-generated content, links can pose security risks. The link safety feature adds a confirmation modal before opening external links, similar to ChatGPT's implementation.

Link safety is enabled by default. When a user clicks any link, a confirmation modal appears with:

  • The full URL being opened
  • A "Copy link" button
  • An "Open link" button
  • Close via backdrop click or Escape key

To disable the confirmation modal and allow links to open directly:

import { Streamdown } from 'streamdown';

export default function Chat({ content }) {
  return (
    <Streamdown linkSafety={{ enabled: false }}>
      {content}
    </Streamdown>
  );
}

Use the onLinkCheck callback to allow trusted domains without showing the modal:

<Streamdown
  linkSafety={{
    enabled: true,
    onLinkCheck: (url) => {
      // Return true to allow without modal (safelist)
      // Return false to show confirmation modal
      return url.startsWith('https://your-app.com') ||
             url.startsWith('https://github.com');
    }
  }}
>
  {content}
</Streamdown>

The callback receives the URL and can return:

  • true - Open the link directly without modal
  • false - Show the confirmation modal
  • Promise<boolean> - Async checks are supported

Async Safelist Check

For server-side safelist validation:

<Streamdown
  linkSafety={{
    enabled: true,
    onLinkCheck: async (url) => {
      const response = await fetch('/api/check-url', {
        method: 'POST',
        body: JSON.stringify({ url }),
      });
      const { isSafe } = await response.json();
      return isSafe;
    }
  }}
>
  {content}
</Streamdown>

Replace the default modal with your own component using renderModal:

import { Streamdown, type LinkSafetyModalProps } from 'streamdown';

function CustomLinkModal({ url, isOpen, onClose, onConfirm }: LinkSafetyModalProps) {
  if (!isOpen) return null;

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h2>External Link</h2>
        <p>You're about to visit:</p>
        <code>{url}</code>
        <div className="actions">
          <button onClick={onClose}>Cancel</button>
          <button onClick={onConfirm}>Continue</button>
        </div>
      </div>
    </div>
  );
}

export default function Chat({ content }) {
  return (
    <Streamdown
      linkSafety={{
        enabled: true,
        renderModal: (props) => <CustomLinkModal {...props} />,
      }}
    >
      {content}
    </Streamdown>
  );
}

The renderModal function receives:

PropTypeDescription
urlstringThe URL being opened
isOpenbooleanWhether the modal is visible
onClose() => voidCall to close the modal
onConfirm() => voidCall to open the link and close the modal

Link safety works alongside content hardening. Use both for comprehensive protection:

import { Streamdown, defaultRehypePlugins } from 'streamdown';
import { harden } from 'rehype-harden';

export default function SecureChat({ content }) {
  return (
    <Streamdown
      linkSafety={{
        enabled: true,
        onLinkCheck: (url) => url.startsWith('https://trusted.com'),
      }}
      rehypePlugins={[
        defaultRehypePlugins.raw,
        [
          harden,
          {
            allowedLinkPrefixes: [
              'https://trusted.com',
              'https://github.com',
            ],
            allowedProtocols: ['https', 'mailto'],
          },
        ],
      ]}
    >
      {content}
    </Streamdown>
  );
}

This provides two layers of protection:

  1. Content hardening - Blocks or rewrites disallowed URLs at render time
  2. Link safety modal - Requires user confirmation before navigation

Import the types for custom modal implementations:

import type { LinkSafetyConfig, LinkSafetyModalProps } from 'streamdown';

const config: LinkSafetyConfig = {
  enabled: true,
  onLinkCheck: (url) => url.startsWith('https://safe.com'),
  renderModal: (props: LinkSafetyModalProps) => <CustomModal {...props} />,
};

LinkSafetyConfig

PropertyTypeDefaultDescription
enabledbooleantrueEnable link interception and modal
onLinkCheck(url: string) => boolean | Promise<boolean>-Optional safelist callback
renderModal(props: LinkSafetyModalProps) => ReactNode-Optional custom modal component

LinkSafetyModalProps

PropertyTypeDescription
urlstringThe URL to be opened
isOpenbooleanModal visibility state
onClose() => voidClose the modal without navigation
onConfirm() => voidConfirm and open the link