`source/_data` YAML can define executable JS via default `!!js/function` (`js-yaml-js-types`.all)
Check List
- I have already read Docs page & Troubleshooting page.
- I have already searched existing issues and they are not help to me.
- I examined error or warning messages and it's difficult to solve.
- I am using the latest version of Hexo. (run
hexo versionto check) - My Node.js is matched the required version.
Expected behavior
YAML files under source/_data/ should be parsed as plain data. Default parsing should not construct JavaScript functions from YAML tags.
If !!js/regexp / !!js/undefined are still needed, only those should be enabled — not !!js/function by default.
Actual behavior
Hexo’s YAML renderer enables js-yaml-js-types.all by default:
https://github.com/hexojs/hexo/blob/master/lib/plugins/renderer/yaml.ts
schema = yaml.DEFAULT_SCHEMA.extend(require('js-yaml-js-types').all);That includes !!js/function. A source/_data/*.yml file can define a real Function (for example on toString). When a theme renders {{ site.data.menu }}, Nunjucks stringifies the object, calls that function, and arbitrary Node.js code runs in the Hexo process.
js-yaml v4 made these tags opt-in; re-enabling .all by default is unexpected for site data files.
How to reproduce?
- Create a minimal Hexo site with
[email protected]and a theme layout containing:
{{ site.data.menu }}- Create
source/_data/menu.yml:
toString: !!js/function 'function (){ process.getBuiltinModule("fs").writeFileSync("/tmp/hexo_js_function","1"); return ""; }'
Home: /- Load the site and render that template (same path themes use when printing
site.data):
const Hexo = require('hexo');
const nunjucks = require(require.resolve('nunjucks', { paths: [require.resolve('hexo')] }));
(async () => {
const hexo = new Hexo(process.cwd(), { silent: true });
await hexo.init();
await hexo.load();
const menu = hexo.locals.get('data').menu;
console.log(typeof menu.toString); // function
nunjucks.renderString('{{ site.data.menu }}', { site: { data: { menu } } });
})();- Observe that
/tmp/hexo_js_functionis created with contents1.
Is the problem still there under Safe mode?
Yes. This comes from Hexo’s built-in YAML renderer (lib/plugins/renderer/yaml.ts), not from a third-party plugin/script. Disabling plugins does not remove this schema extension.
Your Node.js & npm version
node v22.22.0
npm 9.2.0Your Hexo and Plugin version
Your package.json
{
"name": "hexo-yaml-jsfunction-repro",
"private": true,
"hexo": {},
"dependencies": {
"hexo": "8.1.2"
}
}Your site's _config.yml (Optional)
Others
Suggested fix
- Do not use
js-yaml-js-types.all by default. - Keep the default safe schema, or extend only
regexp/undefinedif still required. - If
!!js/functionmust remain for compatibility, make it an explicit opt-in (default off).
Source: hexojs/hexo