nixpkgs: allow packages to be marked insecure
If a package's meta has `knownVulnerabilities`, like so: stdenv.mkDerivation { name = "foobar-1.2.3"; ... meta.knownVulnerabilities = [ "CVE-0000-00000: remote code execution" "CVE-0000-00001: local privilege escalation" ]; } and a user attempts to install the package, they will be greeted with a warning indicating that maybe they don't want to install it: error: Package ‘foobar-1.2.3’ in ‘...default.nix:20’ is marked as insecure, refusing to evaluate. Known issues: - CVE-0000-00000: remote code execution - CVE-0000-00001: local privilege escalation You can install it anyway by whitelisting this package, using the following methods: a) for `nixos-rebuild` you can add ‘foobar-1.2.3’ to `nixpkgs.config.permittedInsecurePackages` in the configuration.nix, like so: { nixpkgs.config.permittedInsecurePackages = [ "foobar-1.2.3" ]; } b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add ‘foobar-1.2.3’ to `permittedInsecurePackages` in ~/.config/nixpkgs/config.nix, like so: { permittedInsecurePackages = [ "foobar-1.2.3" ]; } Adding either of these configurations will permit this specific version to be installed. A third option also exists: NIXPKGS_ALLOW_INSECURE=1 nix-build ... though I specifically avoided having a global file-based toggle to disable this check. This way, users don't disable it once in order to get a single package, and then don't realize future packages are insecure.
This commit is contained in:
parent
d36b1ccc13
commit
a9c875fc2e
@ -4,83 +4,213 @@
|
||||
|
||||
<title>Global configuration</title>
|
||||
|
||||
<para>Nix packages can be configured to allow or deny certain options.</para>
|
||||
<para>Nix comes with certain defaults about what packages can and
|
||||
cannot be installed, based on a package's metadata. By default, Nix
|
||||
will prevent installation if any of the following criteria are
|
||||
true:</para>
|
||||
|
||||
<para>To apply the configuration edit
|
||||
<filename>~/.config/nixpkgs/config.nix</filename> and set it like
|
||||
<itemizedlist>
|
||||
<listitem><para>The packages is thought to be broken, and has had
|
||||
its <literal>meta.broken</literal> set to
|
||||
<literal>true</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>The package's <literal>meta.license</literal> is set
|
||||
to a license which is considered to be unfree.</para></listitem>
|
||||
|
||||
<listitem><para>The package has known security vulnerabilities but
|
||||
has not or can not be updated for some reason, and a list of issues
|
||||
has been entered in to the package's
|
||||
<literal>meta.knownVulnerabilities</literal>.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Each of these criteria can be altering the nixpkgs
|
||||
configuration.</para>
|
||||
|
||||
<para>The nixpkgs configuration for a NixOS system is set in the
|
||||
<literal>configuration.nix</literal>, as in the following example:
|
||||
<programlisting>
|
||||
{
|
||||
nixpkgs.config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
However, this does not allow unfree software for individual users.
|
||||
Their configurations are managed separately.</para>
|
||||
|
||||
<para>A user's of nixpkgs configuration is stored in a user-specific
|
||||
configuration file located at
|
||||
<filename>~/.config/nixpkgs/config.nix</filename>. For example:
|
||||
<programlisting>
|
||||
{
|
||||
allowUnfree = true;
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
and will allow the Nix package manager to install unfree licensed packages.</para>
|
||||
<section xml:id="sec-allow-broken">
|
||||
<title>Installing broken packages</title>
|
||||
|
||||
<para>The configuration as listed also applies to NixOS under
|
||||
<option>nixpkgs.config</option> set.</para>
|
||||
|
||||
<itemizedlist>
|
||||
<para>There are two ways to try compiling a package which has been
|
||||
marked as broken.</para>
|
||||
|
||||
<listitem>
|
||||
<para>Allow installing of packages that are distributed under
|
||||
unfree license by setting <programlisting>allowUnfree =
|
||||
true;</programlisting> or deny them by setting it to
|
||||
<literal>false</literal>.</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
For allowing the build of a broken package once, you can use an
|
||||
environment variable for a single invocation of the nix tools:
|
||||
|
||||
<para>Same can be achieved by setting the environment variable:
|
||||
<programlisting>$ export NIXPKGS_ALLOW_BROKEN=1</programlisting>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
For permanently allowing broken packages to be built, you may
|
||||
add <literal>allowBroken = true;</literal> to your user's
|
||||
configuration file, like this:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
allowBroken = true;
|
||||
}</programlisting>
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-allow-unfree">
|
||||
<title>Installing unfree packages</title>
|
||||
|
||||
<para>There are several ways to tweak how Nix handles a package
|
||||
which has been marked as unfree.</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
To temporarily allow all unfree packages, you can use an
|
||||
environment variable for a single invocation of the nix tools:
|
||||
|
||||
<programlisting>$ export NIXPKGS_ALLOW_UNFREE=1</programlisting>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
It is possible to permanently allow individual unfree packages,
|
||||
while still blocking unfree packages by default using the
|
||||
<literal>allowUnfreePredicate</literal> configuration
|
||||
option in the user configuration file.</para>
|
||||
|
||||
<para>This option is a function which accepts a package as a
|
||||
parameter, and returns a boolean. The following example
|
||||
configuration accepts a package and always returns false:
|
||||
<programlisting>
|
||||
{
|
||||
allowUnfreePredicate = (pkg: false);
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>A more useful example, the following configuration allows
|
||||
only allows flash player and visual studio code:
|
||||
|
||||
<programlisting>
|
||||
$ export NIXPKGS_ALLOW_UNFREE=1
|
||||
{
|
||||
allowUnfreePredicate = (pkg: elem (builtins.parseDrvName pkg.name).name [ "flashplayer" "vscode" ]);
|
||||
}
|
||||
</programlisting>
|
||||
</para></listitem>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>It is also possible to whitelist and blacklist licenses
|
||||
that are specifically acceptable or not acceptable, using
|
||||
<literal>whitelistedLicenses</literal> and
|
||||
<literal>blacklistedLicenses</literal>, respectively.
|
||||
</para>
|
||||
|
||||
<listitem>
|
||||
<para>Whenever unfree packages are not allowed, single packages
|
||||
can still be allowed by a predicate function that accepts package
|
||||
as an argument and should return a boolean:
|
||||
<para>The following example configuration whitelists the
|
||||
licenses <literal>amd</literal> and <literal>wtfpl</literal>:
|
||||
|
||||
<programlisting>
|
||||
allowUnfreePredicate = (pkg: ...);
|
||||
{
|
||||
whitelistedLicenses = with stdenv.lib.licenses; [ amd wtfpl ];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
Example to allow flash player and visual studio code only:
|
||||
<para>The following example configuration blacklists the
|
||||
<literal>gpl3</literal> and <literal>agpl3</literal> licenses:
|
||||
|
||||
<programlisting>
|
||||
allowUnfreePredicate = with builtins; (pkg: elem (parseDrvName pkg.name).name [ "flashplayer" "vscode" ]);
|
||||
{
|
||||
blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
<para>A complete list of licenses can be found in the file
|
||||
<filename>lib/licenses.nix</filename> of the nixpkgs tree.</para>
|
||||
</section>
|
||||
|
||||
<listitem>
|
||||
<para>Whenever unfree packages are not allowed, packages can still
|
||||
be whitelisted by their license:
|
||||
|
||||
<section xml:id="sec-allow-insecure">
|
||||
<title>
|
||||
Installing insecure packages
|
||||
</title>
|
||||
|
||||
<para>There are several ways to tweak how Nix handles a package
|
||||
which has been marked as unfree.</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
To temporarily allow all insecure packages, you can use an
|
||||
environment variable for a single invocation of the nix tools:
|
||||
|
||||
<programlisting>$ export NIXPKGS_ALLOW_INSECURE=1</programlisting>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
It is possible to permanently allow individual insecure
|
||||
packages, while still blocking other insecure packages by
|
||||
default using the <literal>permittedInsecurePackages</literal>
|
||||
configuration option in the user configuration file.</para>
|
||||
|
||||
<para>The following example configuration permits the
|
||||
installation of the hypothetically insecure package
|
||||
<literal>hello</literal>, version <literal>1.2.3</literal>:
|
||||
<programlisting>
|
||||
{
|
||||
permittedInsecurePackages = [
|
||||
"hello-1.2.3"
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem><para>
|
||||
It is also possible to create a custom policy around which
|
||||
insecure packages to allow and deny, by overriding the
|
||||
<literal>allowInsecurePredicate</literal> configuration
|
||||
option.</para>
|
||||
|
||||
<para>The <literal>allowInsecurePredicate</literal> option is a
|
||||
function which accepts a package and returns a boolean, much
|
||||
like <literal>allowUnfreePredicate</literal>.</para>
|
||||
|
||||
<para>The following configuration example only allows insecure
|
||||
packages with very short names:
|
||||
|
||||
<programlisting>
|
||||
whitelistedLicenses = with stdenv.lib.licenses; [ amd wtfpl ];
|
||||
{
|
||||
allowInsecurePredicate = (pkg: (builtins.stringLength (builtins.parseDrvName pkg.name).name) <= 5);
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>In addition to whitelisting licenses which are denied by the
|
||||
<literal>allowUnfree</literal> setting, you can also explicitely
|
||||
deny installation of packages which have a certain license:
|
||||
|
||||
<programlisting>
|
||||
blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>A complete list of licenses can be found in the file
|
||||
<filename>lib/licenses.nix</filename> of the nix package tree.</para>
|
||||
</para>
|
||||
|
||||
<para>Note that <literal>permittedInsecurePackages</literal> is
|
||||
only checked if <literal>allowInsecurePredicate</literal> is not
|
||||
specified.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
|
@ -30,6 +30,14 @@ has the following highlights: </para>
|
||||
<listitem>
|
||||
<para>PHP now defaults to PHP 7.1</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Packages in nixpkgs can be marked as insecure through listed
|
||||
vulnerabilities. See the <link
|
||||
xlink:href="https://nixos.org/nixpkgs/manual/#sec-allow-insecure">Nixpkgs
|
||||
manual</link> for more information.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>The following new services were added since the last release:</para>
|
||||
|
@ -75,6 +75,14 @@ let
|
||||
isUnfree (lib.lists.toList attrs.meta.license) &&
|
||||
!allowUnfreePredicate attrs;
|
||||
|
||||
allowInsecureDefaultPredicate = x: builtins.elem x.name (config.permittedInsecurePackages or []);
|
||||
allowInsecurePredicate = x: (config.allowUnfreePredicate or allowInsecureDefaultPredicate) x;
|
||||
|
||||
hasAllowedInsecure = attrs:
|
||||
(attrs.meta.knownVulnerabilities or []) == [] ||
|
||||
allowInsecurePredicate attrs ||
|
||||
builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
|
||||
|
||||
showLicense = license: license.shortName or "unknown";
|
||||
|
||||
defaultNativeBuildInputs = extraBuildInputs ++
|
||||
@ -137,24 +145,62 @@ let
|
||||
builtins.unsafeGetAttrPos "name" attrs;
|
||||
pos'' = if pos' != null then "‘" + pos'.file + ":" + toString pos'.line + "’" else "«unknown-file»";
|
||||
|
||||
throwEvalHelp = { reason, errormsg }:
|
||||
# uppercase the first character of string s
|
||||
let up = s: with lib;
|
||||
(toUpper (substring 0 1 s)) + (substring 1 (stringLength s) s);
|
||||
in
|
||||
assert builtins.elem reason ["unfree" "broken" "blacklisted"];
|
||||
|
||||
throw ("Package ‘${attrs.name or "«name-missing»"}’ in ${pos''} ${errormsg}, refusing to evaluate."
|
||||
+ (lib.strings.optionalString (reason != "blacklisted") ''
|
||||
|
||||
remediation = {
|
||||
unfree = remediate_whitelist "Unfree";
|
||||
broken = remediate_whitelist "Broken";
|
||||
blacklisted = x: "";
|
||||
insecure = remediate_insecure;
|
||||
};
|
||||
remediate_whitelist = allow_attr: attrs:
|
||||
''
|
||||
a) For `nixos-rebuild` you can set
|
||||
{ nixpkgs.config.allow${up reason} = true; }
|
||||
{ nixpkgs.config.allow${allow_attr} = true; }
|
||||
in configuration.nix to override this.
|
||||
|
||||
b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
|
||||
{ allow${up reason} = true; }
|
||||
{ allow${allow_attr} = true; }
|
||||
to ~/.config/nixpkgs/config.nix.
|
||||
''));
|
||||
'';
|
||||
|
||||
remediate_insecure = attrs:
|
||||
''
|
||||
|
||||
Known issues:
|
||||
|
||||
'' + (lib.fold (issue: default: "${default} - ${issue}\n") "" attrs.meta.knownVulnerabilities) + ''
|
||||
|
||||
You can install it anyway by whitelisting this package, using the
|
||||
following methods:
|
||||
|
||||
a) for `nixos-rebuild` you can add ‘${attrs.name or "«name-missing»"}’ to
|
||||
`nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
|
||||
like so:
|
||||
|
||||
{
|
||||
nixpkgs.config.permittedInsecurePackages = [
|
||||
"${attrs.name or "«name-missing»"}"
|
||||
];
|
||||
}
|
||||
|
||||
b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
|
||||
‘${attrs.name or "«name-missing»"}’ to `permittedInsecurePackages` in
|
||||
~/.config/nixpkgs/config.nix, like so:
|
||||
|
||||
{
|
||||
permittedInsecurePackages = [
|
||||
"${attrs.name or "«name-missing»"}"
|
||||
];
|
||||
}
|
||||
|
||||
'';
|
||||
|
||||
|
||||
throwEvalHelp = { reason , errormsg ? "" }:
|
||||
throw (''
|
||||
Package ‘${attrs.name or "«name-missing»"}’ in ${pos''} ${errormsg}, refusing to evaluate.
|
||||
|
||||
'' + ((builtins.getAttr reason remediation) attrs));
|
||||
|
||||
# Check if a derivation is valid, that is whether it passes checks for
|
||||
# e.g brokenness or license.
|
||||
@ -171,6 +217,8 @@ let
|
||||
{ valid = false; reason = "broken"; errormsg = "is marked as broken"; }
|
||||
else if !allowBroken && attrs.meta.platforms or null != null && !lib.lists.elem result.system attrs.meta.platforms then
|
||||
{ valid = false; reason = "broken"; errormsg = "is not supported on ‘${result.system}’"; }
|
||||
else if !(hasAllowedInsecure attrs) then
|
||||
{ valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
|
||||
else { valid = true; };
|
||||
|
||||
outputs' =
|
||||
|
Loading…
Reference in New Issue
Block a user