diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/flake/config.cc | 54 | ||||
-rw-r--r-- | src/libfetchers/fetch-settings.cc | 43 | ||||
-rw-r--r-- | src/libfetchers/fetch-settings.hh | 16 |
3 files changed, 90 insertions, 23 deletions
diff --git a/src/libexpr/flake/config.cc b/src/libexpr/flake/config.cc index b330d96f9..adcf7fd10 100644 --- a/src/libexpr/flake/config.cc +++ b/src/libexpr/flake/config.cc @@ -51,30 +51,46 @@ void ConfigFile::apply() else assert(false); - if (!whitelist.count(baseName) && !nix::fetchSettings.acceptFlakeConfig) { - bool trusted = false; - auto trustedList = readTrustedList(); - auto tlname = get(trustedList, name); - if (auto saved = tlname ? get(*tlname, valueS) : nullptr) { - trusted = *saved; - printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS); - } else { - // FIXME: filter ANSI escapes, newlines, \r, etc. - if (std::tolower(logger->ask(fmt("do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "' (y/N)?", name, valueS)).value_or('n')) == 'y') { - trusted = true; - } - if (std::tolower(logger->ask(fmt("do you want to permanently mark this value as %s (y/N)?", trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') { - trustedList[name][valueS] = trusted; - writeTrustedList(trustedList); + bool trusted = whitelist.count(baseName); + if (!trusted) { + switch (nix::fetchSettings.acceptFlakeConfig) { + case AcceptFlakeConfig::True: { + trusted = true; + break; + } + case AcceptFlakeConfig::Ask: { + auto trustedList = readTrustedList(); + auto tlname = get(trustedList, name); + if (auto saved = tlname ? get(*tlname, valueS) : nullptr) { + trusted = *saved; + printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS); + } else { + // FIXME: filter ANSI escapes, newlines, \r, etc. + if (std::tolower(logger->ask(fmt("Do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "' (y/N)? This may allow the flake to gain root, see the nix.conf manual page.", name, valueS)).value_or('n')) == 'y') { + trusted = true; + } else { + warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false); + } + if (std::tolower(logger->ask(fmt("do you want to permanently mark this value as %s (y/N)?", trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') { + trustedList[name][valueS] = trusted; + writeTrustedList(trustedList); + } } + break; } - if (!trusted) { - warn("ignoring untrusted flake configuration setting '%s'.\nPass '%s' to trust it", name, "--accept-flake-config"); - continue; + case nix::AcceptFlakeConfig::False: { + trusted = false; + break; + }; } } - globalConfig.set(name, valueS); + if (trusted) { + debug("accepting trusted flake configuration setting '%s'", name); + globalConfig.set(name, valueS); + } else { + warn("ignoring untrusted flake configuration setting '%s', pass '%s' to trust it (may allow the flake to gain root, see the nix.conf manual page)", name, "--accept-flake-config"); + } } } diff --git a/src/libfetchers/fetch-settings.cc b/src/libfetchers/fetch-settings.cc index e7d5244dc..aeb3c542b 100644 --- a/src/libfetchers/fetch-settings.cc +++ b/src/libfetchers/fetch-settings.cc @@ -1,7 +1,50 @@ +#include "abstract-setting-to-json.hh" +#include "args.hh" +#include "config-impl.hh" #include "fetch-settings.hh" +#include <nlohmann/json.hpp> + namespace nix { +template<> AcceptFlakeConfig BaseSetting<AcceptFlakeConfig>::parse(const std::string & str) const +{ + if (str == "true") return AcceptFlakeConfig::True; + else if (str == "ask") return AcceptFlakeConfig::Ask; + else if (str == "false") return AcceptFlakeConfig::False; + else throw UsageError("option '%s' has invalid value '%s'", name, str); +} + +template<> std::string BaseSetting<AcceptFlakeConfig>::to_string() const +{ + if (value == AcceptFlakeConfig::True) return "true"; + else if (value == AcceptFlakeConfig::Ask) return "ask"; + else if (value == AcceptFlakeConfig::False) return "false"; + else abort(); +} + +template<> void BaseSetting<AcceptFlakeConfig>::convertToArg(Args & args, const std::string & category) +{ + args.addFlag({ + .longName = name, + .description = "Accept Lix configuration options from flakes without confirmation. This allows flakes to gain root access to your machine if you are a trusted user; see the nix.conf manual page for more details.", + .category = category, + .handler = {[this]() { override(AcceptFlakeConfig::True); }} + }); + args.addFlag({ + .longName = "ask-" + name, + .description = "Ask whether to accept Lix configuration options from flakes.", + .category = category, + .handler = {[this]() { override(AcceptFlakeConfig::Ask); }} + }); + args.addFlag({ + .longName = "no-" + name, + .description = "Reject Lix configuration options from flakes.", + .category = category, + .handler = {[this]() { override(AcceptFlakeConfig::False); }} + }); +} + FetchSettings::FetchSettings() { } diff --git a/src/libfetchers/fetch-settings.hh b/src/libfetchers/fetch-settings.hh index 6fb260c3a..93123463c 100644 --- a/src/libfetchers/fetch-settings.hh +++ b/src/libfetchers/fetch-settings.hh @@ -11,6 +11,8 @@ namespace nix { +enum class AcceptFlakeConfig { False, Ask, True }; + struct FetchSettings : public Config { FetchSettings(); @@ -86,15 +88,21 @@ struct FetchSettings : public Config "Whether to use flake registries to resolve flake references.", {}, true, Xp::Flakes}; - Setting<bool> acceptFlakeConfig{this, false, "accept-flake-config", + Setting<AcceptFlakeConfig> acceptFlakeConfig{ + this, AcceptFlakeConfig::Ask, "accept-flake-config", R"( Whether to accept Lix configuration from the `nixConfig` attribute of - a flake without prompting. This is almost always a very bad idea. - - Setting this setting as a trusted user allows Nix flakes to gain root + a flake. Doing so as a trusted user allows Nix flakes to gain root access on your machine if they set one of the several trusted-user-only settings that execute commands as root. + If set to `true`, such configuration will be accepted without asking; + this is almost always a very bad idea. Setting this to `ask` will + prompt the user each time whether to allow a certain configuration + option set this way, and offer to optionally remember their choice. + When set to `false`, the configuration will be automatically + declined. + See [multi-user installations](@docroot@/installation/multi-user.md) for more details on the Lix security model. )", |