Restore support for YAML aliases in data files
ijmorales opened this issue · comments
Expected behavior and actual behavior
Before https://github.com/middleman/middleman/releases/tag/v4.5.0, we were able to use aliases in our YAML files under the data/
directory to avoid duplication. After upgrading to v4.5.0 and due to #2635, we are unable to build the static pages that depend upon data files that use YAML aliases.
I understand that the change from YAML.load
to YAML.safe_load
was necessary since breaking changes were introduced in Ruby 3.1.. What we are looking for as a team is some direction to make our app compatible with the latest version of this gem. I can think of a few options and I'm happy to open a PR, but would like to hear the maintainers take first:
- Change
Middleman::Util#parse_yaml
so it callsYAML.safe_load
withaliases: true
by default. Even though all files under thedata
directory should, in theory, be trusted, this change can potentially make applications more vulnerable to attacks such as YAML bombing, at least in the same way they are in versions prior to 4.5.0. - Keep aliases excluded by default, but add a configuration option to
Data
that users can opt in using theConfigContext
interface that would makePsych
load YAML files with alias support. - Of course, we always have the possibility of patching our own application and load the
YAML
files without theapp.data
abstraction. This is cumbersome because we cannot easily reuse the caching capabilities of theData
extension.
Steps to reproduce the problem (from a clean middleman installation)
- Create a brand new middleman app.
- Add a YAML file under
data
folder, that uses aliases, such as:
# data/jobs.yml
swe:
description: '...'
company_benefits: &company-benefits
- We are awesome.
- Fair enough compensation.
devops:
description: '...'
company_benefits: *company-benefits
- Configure your app to do something with that
data
. For example, we use it to build dynamic pages, one for each job posting:
# config.rb
Domain.locales.each do |locale|
I18n.locale = locale
# Dynamic pages for Jobs
@app.data.jobs[locale]&.each do |job|
proxy "/#{locale}/#{I18n.t('paths.jobs')}/#{job.page_url}/index.html",
'/templates/job-offer.html', locals: { job: job }, lang: locale, ignore: true
end
end
- Verify that it fails with the following message, when trying to parse that YAML:
$ bundle exec middleman build
YAML Exception parsing /home/nacho/workspace/web-src/data/jobs.yml: Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`.
YAML Exception parsing /home/nacho/workspace/web-src/data/jobs.yml: Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`.
YAML Exception parsing /home/nacho/workspace/web-src/data/jobs.yml: Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`.
== Sprockets will render css with SassC
YAML Exception parsing /home/nacho/workspace/web-src/data/jobs.yml: Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`.
Additional information
- Ruby version: 3.2.0
- Middleman version: 4.5.0
- OS version:
Description: Ubuntu 22.04.2 LTS
Release: 22.04
Codename: jammy
I think approach #1 makes sense. This was an accidental regression in the attempt to support Ruby 3.1
Would also be nice to have a test for aliases so it stays working.