Skip to content
This repository was archived by the owner on Apr 9, 2026. It is now read-only.

Commit 4d527fd

Browse files
Merge pull request #498 from hashicorp/version-6.0.0
Get ready for 6.0.0 release
2 parents 17d6598 + ededdf5 commit 4d527fd

13 files changed

Lines changed: 487 additions & 175 deletions

File tree

.prettierrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"semi": false,
3-
"singleQuote": true
2+
"singleQuote": true,
3+
"semi": false
44
}

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export async function getStaticProps() {
292292

293293
This library exposes a function and a component, `serialize` and `<MDXRemote />`. These two are purposefully isolated into their own files -- `serialize` is intended to be run **server-side**, so within `getStaticProps`, which runs on the server/at build time. `<MDXRemote />` on the other hand is intended to be run on the client side, in the browser.
294294

295-
- **`serialize(source: string, { mdxOptions?: object, scope?: object, parseFrontmatter?: boolean })`**
295+
- **`serialize(source: string, { mdxOptions?: object, scope?: object, parseFrontmatter?: boolean, blockJS?: boolean, blockDangerousJS?: boolean })`**
296296

297297
**`serialize`** consumes a string of MDX. It can also optionally be passed options which are [passed directly to MDX](https://mdxjs.com/docs/extending-mdx/), and a scope object that can be included in the MDX scope. The function returns an object that is intended to be passed into `<MDXRemote />` directly.
298298

@@ -313,6 +313,13 @@ This library exposes a function and a component, `serialize` and `<MDXRemote />`
313313
},
314314
// Indicates whether or not to parse the frontmatter from the MDX source
315315
parseFrontmatter: false,
316+
// Block JavaScript expressions in MDX (e.g., {variable}, {func()})
317+
// When true, these expressions are removed. Defaults to true.
318+
blockJS: true,
319+
// Provides a best effort option to block dangerous JavaScript when blockJS is false (JS is allowed).
320+
// Prevents access to eval, Function, process, require, and other dangerous globals.
321+
// Only applies when blockJS is false. Defaults to true for security.
322+
blockDangerousJS: true,
316323
}
317324
)
318325
```
@@ -383,6 +390,18 @@ This library evaluates a string of JavaScript on the client side, which is how i
383390

384391
If you have a CSP on your website that disallows code evaluation via `eval` or `new Function()`, you will need to loosen that restriction in order to utilize `next-mdx-remote`, which can be done using [`unsafe-eval`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#common_sources).
385392

393+
### JavaScript Expressions in MDX
394+
395+
By default, JavaScript expressions (like `{variable}` or `{func()}`) are **disabled for security** for versions 6.0.0 and above.
396+
397+
If you need to enable JavaScript expressions:
398+
399+
1. **Trusted content with protection (recommended)**: Set `blockJS: false` in serialize options. By default, `blockDangerousJS: true` is enabled, which will provide a best effort option to blocks dangerous operations like `eval`, `Function`, `process`, `require`, and other globals that could lead to remote code execution (RCE).
400+
401+
2. **Completely trusted content only**: Set both `blockJS: false` and `blockDangerousJS: false` to allow all JavaScript.
402+
403+
**Warning:** Only set `blockDangerousJS: false` if you completely trust the MDX content source. This removes critical security protections and could allow RCE attacks.
404+
386405
## TypeScript
387406

388407
This project does include native types for TypeScript use. Both `serialize` and `<MDXRemote />` have types normally as you'd expect, and the library also exports a type which you can use to type the result of `getStaticProps`.

__tests__/fixtures/basic/pages/index.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export async function getStaticProps() {
6060
const mdxSource = await serialize(source, {
6161
mdxOptions: { remarkPlugins: [paragraphCustomAlerts] },
6262
parseFrontmatter: true,
63+
blockJS: false,
6364
})
6465

6566
return { props: { mdxSource } }

__tests__/fixtures/rsc/app/app-dir-mdx/compile-mdx/page.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export default async function Page() {
2525
options: {
2626
mdxOptions: { remarkPlugins: [] },
2727
parseFrontmatter: true,
28+
blockJS: false,
2829
},
2930
})
3031

__tests__/fixtures/rsc/app/app-dir-mdx/mdxremote/page.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default async function Page() {
2727
options={{
2828
mdxOptions: { remarkPlugins: [] },
2929
parseFrontmatter: true,
30+
blockJS: false,
3031
}}
3132
/>
3233
</>

__tests__/serialize.test.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ describe('serialize', () => {
5555
scope: {
5656
bar: 'test',
5757
},
58+
blockJS: false,
5859
})
5960
expect(result).toMatchInlineSnapshot(`"<p>test</p>"`)
6061
})
@@ -151,7 +152,7 @@ export const bar = 'bar'`
151152

152153
const result = await renderStatic(
153154
`<Test content={<>Rendering a fragment</>} />`,
154-
{ components }
155+
{ components, blockJS: false }
155156
)
156157
expect(result).toMatchInlineSnapshot(`"Rendering a fragment"`)
157158
})
@@ -195,7 +196,7 @@ hello: world
195196
---
196197
197198
# Hello {frontmatter.hello}`,
198-
{ parseFrontmatter: true }
199+
{ parseFrontmatter: true, blockJS: false }
199200
)
200201

201202
expect(result).toMatchInlineSnapshot(`"<h1>Hello world</h1>"`)

__tests__/utils.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ export async function renderStatic(
3030
scope = {},
3131
mdxOptions,
3232
parseFrontmatter,
33+
blockJS,
34+
blockDangerousJS,
3335
}: Partial<SerializeOptions & Pick<MDXRemoteProps, 'components'>> = {}
3436
): Promise<string> {
3537
const mdxSource = await serialize(mdx, {
3638
mdxOptions,
3739
parseFrontmatter,
40+
blockJS,
41+
blockDangerousJS,
3842
})
3943

4044
return ReactDOMServer.renderToStaticMarkup(

0 commit comments

Comments
 (0)