middleman / middleman

Hand-crafted frontend development

Home Page:https://middlemanapp.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

  1. Change Middleman::Util#parse_yaml so it calls YAML.safe_load with aliases: true by default. Even though all files under the data 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.
  2. Keep aliases excluded by default, but add a configuration option to Data that users can opt in using the ConfigContext interface that would make Psych load YAML files with alias support.
  3. Of course, we always have the possibility of patching our own application and load the YAML files without the app.data abstraction. This is cumbersome because we cannot easily reuse the caching capabilities of the Data extension.

Steps to reproduce the problem (from a clean middleman installation)

  1. Create a brand new middleman app.
  2. 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
  1. 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
  1. 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.