Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write Ruby in your Front Matter (yes, really!) #9

Closed
wants to merge 15 commits into from

Conversation

jaredcwhite
Copy link
Member

@jaredcwhite jaredcwhite commented Apr 20, 2020

DEMO: https://deploy-preview-9--bridgetownrb.netlify.app/ (the monthly commits number in the footer is dynamically pulled from GitHub's API during site build)


Now we're really getting wild. 😱

This PR adds the ability to define Ruby code which will get resolved as the value of a front matter variable. It's very much inspired by gray-matter used by Eleventy, Gatsby, and others, where you can write "Javascript front matter" to execute code as part of the parsing of the front matter.

In this case, the front matter is still YAML, but we whitelist a special string subclass (Rb) and use that as a tag to indicate to the system the string isn't just any string but a block of Ruby code.

Example (used in the website update included in this PR):

---
github_participation: !ruby/string:Rb |
  require "faraday"
  endpoint = "https://api.github.com/repos/bridgetownrb/bridgetown/stats/participation"

  resp = Faraday.get(
    endpoint,
    nil,
    {"Accept": "application/vnd.github.v3+json"}
  )
  json = JSON.parse(resp.body)
  json["all"][-4..].sum
---

This is attached to the default layout, which means the footer partial can now use the Ruby output:

Monthly GitHub Commits: <strong>{{ layout.github_participation }}</strong>

Awesome sauce!

Security

When I first realized you could actually execute Javascript in front matter using, say, Eleventy, I was flummoxed. Isn't that a gaping security hole? Isn't that the whole point of using safe_yaml to parse front matter? Surely it's madness, MADNESS to have executable code in a website document!

But as I gave it more thought, it dawned on me that any website codebase itself is really one huge application with the ability to write custom Ruby plugins (Liquid tags, generators, whatever) that can do literally anything to a computer. That's why GitHub had to go through lots of hoops with GitHub Pages to switch off Jekyll's custom plugin features, in order to have a "safe" execution context.

However, the method so many people have switched to now with Jamstack sites is everything's executed in containers (or a local dev machine), which means the potential damage due to a script rummaging around the file system during a build process is quite minimized. And again, what you could do in Ruby front matter, you could do in a plugin as well…same codebase.

BUT…what about when you are using a CMS for non-technical people, and thus you are pulling in pages submitted by the "outside world" and committing them into the codebase? That's where I think it becomes murky. There's definitely a potential attack vector in that sort of scenario.

Thus, This is Turned OFF By Default. Turn on with an ENV var

This feature will require the ENV var BRIDGETOWN_RUBY_IN_FRONT_MATTER to be set to "true". It's also possible, even with the var set to true, to turn it off in the config file via ruby_in_front_matter: false. We'll keep on eye on how this functionality is received and how it gets used and maybe down the road it'll make sense to relax this guard. But for now, better to be safe than sorry.

All that to say, I'm extremely excited about this feature and will get to work on documenting a bunch of the neat aspects of how this works in future PRs.

@jaredcwhite jaredcwhite added the enhancement New feature or request label Apr 20, 2020
@jaredcwhite
Copy link
Member Author

Another idea would be to add a configurable "whitelisted layout / document" option so that the site could define exactly which layouts or documents are permitted to use Ruby front matter and nothing else goes through…and that could line up with how a CMS is set up so no outside code will leak in. Just a thought…

@jaredcwhite
Copy link
Member Author

I revamped this a little bit so it's not quite as draconian of a security measure.

The ruby_in_front_matter config option is now true by default. So all you'll need to do to enable this feature is make sure the ENV var BRIDGETOWN_RUBY_IN_FRONT_MATTER is set to "true". That's it. Obviously if the ENV var is true but you want to disable it in the site config, you can set ruby_in_front_matter to false.

I think this strikes the right balance. If I get feedback to the contrary, I'm happy to re-evaluate.

@jaredcwhite jaredcwhite added this to the v0.13.0 "Klickitat" milestone May 1, 2020
@jaredcwhite jaredcwhite added this to In progress in Spring 2020 via automation May 1, 2020
@jaredcwhite jaredcwhite added the documentation Improvements or additions to documentation label May 2, 2020
@jaredcwhite
Copy link
Member Author

This was merged in manually to the master branch earlier in the week. Done! :shipit:

@jaredcwhite jaredcwhite closed this May 7, 2020
Spring 2020 automation moved this from In progress to Done May 7, 2020
@jaredcwhite jaredcwhite deleted the inline-ruby-front-matter branch May 28, 2020 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
No open projects
Spring 2020
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

1 participant