Skip to content

Commit 59076c8

Browse files
gatsbybotLekoArts
andauthored
fix(gatsby-transformer-remark): Disallow JS frontmatter by default (#37244) (#37298)
(cherry picked from commit 77b8ccd) Co-authored-by: Lennart <lekoarts@gmail.com>
1 parent 48a3db4 commit 59076c8

File tree

3 files changed

+154
-73
lines changed

3 files changed

+154
-73
lines changed

packages/gatsby-transformer-remark/README.md

+85-56
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,46 @@ Parses Markdown files using [remark](http://remark.js.org/).
44

55
## Install
66

7-
`npm install gatsby-transformer-remark`
8-
9-
## How to use
10-
11-
```javascript
12-
// In your gatsby-config.js
13-
plugins: [
14-
{
15-
resolve: `gatsby-transformer-remark`,
16-
options: {
17-
// Footnotes mode (default: true)
18-
footnotes: true,
19-
// GitHub Flavored Markdown mode (default: true)
20-
gfm: true,
21-
// Plugins configs
22-
plugins: [],
7+
Install the plugin to your site:
8+
9+
```shell
10+
npm install gatsby-transformer-remark
11+
```
12+
13+
Add it to your `gatsby-config`:
14+
15+
```js:title=gatsby-config.js
16+
module.exports = {
17+
plugins: [
18+
{
19+
resolve: `gatsby-transformer-remark`,
20+
options: {},
2321
},
24-
},
25-
],
22+
],
23+
}
24+
```
25+
26+
## Options
27+
28+
```js:title=gatsby-config.js
29+
module.exports = {
30+
plugins: [
31+
{
32+
resolve: `gatsby-transformer-remark`,
33+
options: {
34+
// Footnotes mode (default: true)
35+
footnotes: true,
36+
// GitHub Flavored Markdown mode (default: true)
37+
gfm: true,
38+
// Add your gatsby-remark-* plugins here
39+
plugins: [],
40+
// Enable JS for https://github.com/jonschlinkert/gray-matter#optionsengines (default: false)
41+
// It's not advised to set this to "true" and this option will likely be removed in the future
42+
jsFrontmatterEngine: false,
43+
},
44+
},
45+
],
46+
}
2647
```
2748

2849
The following parts of `options` enable the `remark-footnotes` and `remark-gfm`
@@ -31,10 +52,30 @@ plugins:
3152
- `options.footnotes`
3253
- `options.gfm`
3354

34-
A full explanation of how to use markdown in Gatsby can be found here:
35-
[Adding Markdown Pages](https://www.gatsbyjs.com/docs/how-to/routing/adding-markdown-pages/)
55+
A full explanation of how to use markdown in Gatsby can be found here: [Adding Markdown Pages](https://www.gatsbyjs.com/docs/how-to/routing/adding-markdown-pages/)
56+
57+
There are many `gatsby-remark-*` plugins which you can install to customize how Markdown is processed. Check out the [source code for using-remark](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-remark) as an example.
58+
59+
### `gray-matter` options
60+
61+
`gatsby-transformer-remark` uses [gray-matter](https://github.com/jonschlinkert/gray-matter) to parse Markdown frontmatter, so you can specify any of the options mentioned [in its README](https://github.com/jonschlinkert/gray-matter#options) in the `options` key of the plugin.
3662

37-
There are many Gatsby Remark plugins which you can install to customize how Markdown is processed. Many of them are demoed at https://using-remark.gatsbyjs.org/. See also the [source code for using-remark](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-remark).
63+
**Example: Excerpts**
64+
65+
If you don't want to use `pruneLength` for excerpts but a custom separator, you can specify an `excerpt_separator`:
66+
67+
```js:title=gatsby-config.js
68+
module.exports = {
69+
plugins: [
70+
{
71+
resolve: `gatsby-transformer-remark`,
72+
options: {
73+
excerpt_separator: `<!-- end -->`
74+
}
75+
},
76+
],
77+
}
78+
```
3879

3980
## Parsing algorithm
4081

@@ -120,19 +161,20 @@ By default, `absolute` is set to `false`, generating a relative path. If you'd l
120161

121162
To pass default options to the plugin generating the `tableOfContents`, configure it in `gatsby-config.js` as shown below. The options shown below are the defaults used by the plugin.
122163

123-
```javascript
124-
// In your gatsby-config.js
125-
plugins: [
126-
{
127-
resolve: `gatsby-transformer-remark`,
128-
options: {
129-
tableOfContents: {
130-
heading: null,
131-
maxDepth: 6,
164+
```js:title=gatsby-config.js
165+
module.exports = {
166+
plugins: [
167+
{
168+
resolve: `gatsby-transformer-remark`,
169+
options: {
170+
tableOfContents: {
171+
heading: null,
172+
maxDepth: 6,
173+
},
132174
},
133175
},
134-
},
135-
]
176+
],
177+
}
136178
```
137179

138180
### Excerpts
@@ -198,23 +240,6 @@ You can also get excerpts in Markdown format.
198240
}
199241
```
200242

201-
## `gray-matter` options
202-
203-
`gatsby-transformer-remark` uses [gray-matter](https://github.com/jonschlinkert/gray-matter) to parse Markdown frontmatter, so you can specify any of the options mentioned [here](https://github.com/jonschlinkert/gray-matter#options) in the `gatsby-config.js` file.
204-
205-
### Example: Excerpts
206-
207-
If you don't want to use `pruneLength` for excerpts but a custom separator, you can specify an `excerpt_separator` in the `gatsby-config.js` file:
208-
209-
```javascript
210-
{
211-
"resolve": `gatsby-transformer-remark`,
212-
"options": {
213-
"excerpt_separator": `<!-- end -->`
214-
}
215-
}
216-
```
217-
218243
Any file that does not have the given `excerpt_separator` will fall back to the default pruning method.
219244

220245
## Troubleshooting
@@ -237,14 +262,18 @@ If that is the case, you can set `truncate` option on `excerpt` field, like:
237262

238263
If your Markdown file contains HTML, `excerpt` will not return a value.
239264

240-
In that case, you can set an `excerpt_separator` in the `gatsby-config.js` file:
265+
In that case, you can set an `excerpt_separator` in the `gatsby-config`:
241266

242-
```javascript
243-
{
244-
"resolve": `gatsby-transformer-remark`,
245-
"options": {
246-
"excerpt_separator": `<!-- endexcerpt -->`
247-
}
267+
```js:title=gatsby-config.js
268+
module.exports = {
269+
plugins: [
270+
{
271+
resolve: `gatsby-transformer-remark`,
272+
options: {
273+
excerpt_separator: `<!-- endexcerpt -->`
274+
},
275+
},
276+
],
248277
}
249278
```
250279

packages/gatsby-transformer-remark/src/__tests__/gatsby-node.js

+28-17
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,43 @@ describe(`gatsby-node.js`, () => {
77
`"footnotes" must be a boolean`,
88
`"gfm" must be a boolean`,
99
`"plugins" must be an array`,
10+
`"jsFrontmatterEngine" must be a boolean`,
1011
]
1112

12-
const { errors } = await testPluginOptionsSchema(pluginOptionsSchema, {
13-
footnotes: `this should be a boolean`,
14-
gfm: `this should be a boolean`,
15-
plugins: `this should be an array`,
16-
})
13+
const { errors, isValid } = await testPluginOptionsSchema(
14+
pluginOptionsSchema,
15+
{
16+
footnotes: `this should be a boolean`,
17+
gfm: `this should be a boolean`,
18+
plugins: `this should be an array`,
19+
jsFrontmatterEngine: `this should be a boolean`,
20+
}
21+
)
1722

23+
expect(isValid).toBe(false)
1824
expect(errors).toEqual(expectedErrors)
1925
})
2026

2127
it(`should validate the schema`, async () => {
22-
const { isValid } = await testPluginOptionsSchema(pluginOptionsSchema, {
23-
footnotes: false,
24-
gfm: false,
25-
plugins: [
26-
`gatsby-remark-copy-linked-files`,
27-
{
28-
resolve: `gatsby-remark-images`,
29-
options: {
30-
maxWidth: 756,
28+
const { isValid, errors } = await testPluginOptionsSchema(
29+
pluginOptionsSchema,
30+
{
31+
footnotes: false,
32+
gfm: false,
33+
plugins: [
34+
`gatsby-remark-copy-linked-files`,
35+
{
36+
resolve: `gatsby-remark-images`,
37+
options: {
38+
maxWidth: 756,
39+
},
3140
},
32-
},
33-
],
34-
})
41+
],
42+
jsFrontmatterEngine: true,
43+
}
44+
)
3545

3646
expect(isValid).toBe(true)
47+
expect(errors).toEqual([])
3748
})
3849
})

packages/gatsby-transformer-remark/src/gatsby-node.js

+41
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ exports.unstable_shouldOnCreateNode = unstable_shouldOnCreateNode
77
exports.createSchemaCustomization = require(`./create-schema-customization`)
88
exports.setFieldsOnGraphQLNodeType = require(`./extend-node-type`)
99

10+
// Dedupe warning
11+
let warnedAboutJSFrontmatterEngine = false
12+
1013
exports.pluginOptionsSchema = function ({ Joi }) {
1114
return Joi.object({
1215
footnotes: Joi.boolean().description(
@@ -21,5 +24,43 @@ exports.pluginOptionsSchema = function ({ Joi }) {
2124
plugins: Joi.subPlugins().description(
2225
`A list of remark plugins. See also: https://github.com/gatsbyjs/gatsby/tree/master/examples/using-remark for examples`
2326
),
27+
// TODO(v6): Remove and disallow any custom engines (including JS)
28+
jsFrontmatterEngine: Joi.boolean()
29+
.default(false)
30+
.description(
31+
`Enable JS for https://github.com/jonschlinkert/gray-matter#optionsengines`
32+
),
33+
}).custom(value => {
34+
const { jsFrontmatterEngine, engines = {} } = value || {}
35+
36+
if (jsFrontmatterEngine) {
37+
// show this warning only once in main process
38+
if (!process.env.GATSBY_WORKER_ID) {
39+
console.warn(
40+
`JS frontmatter engine is enabled in gatsby-transformer-remark (via jsFrontmatterEngine: true). This can cause a security risk, see https://github.com/gatsbyjs/gatsby/security/advisories/GHSA-7ch4-rr99-cqcw. If you are not relying on this feature we strongly suggest disabling it via the "jsFrontmatterEngine: false" plugin option. If you rely on this feature make sure to properly secure or sanitize your content source.`
41+
)
42+
}
43+
return value
44+
}
45+
46+
const js = () => {
47+
if (!warnedAboutJSFrontmatterEngine) {
48+
console.warn(
49+
`You have frontmatter declared with "---js" or "---javascript" that is not parsed by default to mitigate a security risk (see https://github.com/gatsbyjs/gatsby/security/advisories/GHSA-7ch4-rr99-cqcw). If you require this feature it can be enabled by setting "jsFrontmatterEngine: true" in the plugin options of gatsby-transformer-remark.`
50+
)
51+
warnedAboutJSFrontmatterEngine = true
52+
}
53+
// we still have to return a frontmatter, so we just stub it with empty object
54+
return {}
55+
}
56+
57+
return {
58+
...value,
59+
engines: {
60+
...engines,
61+
js,
62+
javascript: js,
63+
},
64+
}
2465
})
2566
}

0 commit comments

Comments
 (0)