[SOLVED] hardeningDisable and bundlerEnv

Hello! I have a Ruby app which I want to develop using nix-shell. The problem is that the app depends on a gem which is a C extension and it fails to compile because it uses format strings which are not string literals. Unfortunately, the gem seems to be abandoned. I could use a fork, but I want to find out how to resolve this issue using Nix.

I looked up the docs and it turns out that this is a Nix feature called “hardening” and it can be configured using the parameters hardeningEnable and hardeningDisable passed to mkDerivation.

Minimal reproducible example is here.

Gemfile:

# frozen_string_literal: true

source "https://rubygems.org"

gem 'digest-sha3', '= 1.1.0'

bootstrap.nix.

{ pkgs ? import <nixpkgs> {}
}:

pkgs.mkShell {
  buildInputs = [ pkgs.bundix ];

  hardeningDisable = [ "format" ];
}

shell.nix:

{ pkgs ? import <nixpkgs> {}
}:

let
  hardeningDisable = [ "format" ];

  gems = pkgs.bundlerEnv {
    name = "app-gems";
    gemdir = ./.;

    # This doens't make any difference:
    # inherit hardeningDisable;
  };
in pkgs.mkShell {
  buildInputs = with pkgs; [
    ruby
    gems
    bundix
  ];

  inherit hardeningDisable;
}

To bootstrap gemset.nix, I use bootstrap.nix, hardeningDisable helps here:

$ nix-shell bootstrap.nix --run 'bundix --magic'

This successfully builds gemset.nix, but when I try to drop into the main shell (nix-shell shell.nix), building gems fails because of hardening. Passing hardeningDisable to bundlerEnv doesn’t work.

How do I disable/configure hardening for bundlerEnv? Or is there a better way to work around the issue?

Thanks.

Hi!

Try this:

{ pkgs ? import <nixpkgs> {}
}:

let
  gems = pkgs.bundlerEnv {
    name = "app-gems";
    gemdir = ./.;
    gemConfig = pkgs.defaultGemConfig // {
      digest-sha3 = attrs: {
        hardeningDisable = [ "format" ];
      };
    };
  };

in pkgs.mkShell {
  buildInputs = with pkgs; [
    ruby
    gems
    bundix
  ];
}

The issue you are facing is that each ruby gem is it’s own derivation and the parameter wasn’t applied on the right level.

The gemConfig is a sort of callback that will add those attributes to the derivation. We also have a defaultGemConfig set for common gem overrides.

2 Likes

Thanks for the explanation, your solution worked!

Should this override be added to defaultGemConfig? Or is it not worth doing it for less-used gems?

I think sharing a good config for any gems you come across is very helpful for other people :slight_smile: