···248### `lib.sourceTypes.binaryBytecode` {#lib.sourceTypes.binaryBytecode}
249250Code to run on a VM interpreter or JIT compiled into bytecode by a third party. This includes packages which download Java `.jar` files from another source.
251-252-## Software identifiers {#sec-meta-identifiers}
253-254-Package's `meta.identifiers` attribute specifies information about software identifiers associated with this package. Software identifiers are used, for example:
255-* to generate Software Bill of Materials (SBOM) that lists all components used to build the software, which can later be used to perform vulnerability or license analysis of the resulting software;
256-* to lookup software in different vulnerability databases or report new vulnerabilities to them.
257-258-Overriding the default `meta.identifiers` attribute is optional, but it is recommended to fill in pieces to help tools mentioned above get precise data.
259-For example, we could get automatic notifications about potential vulnerabilities for users in the future.
260-All identifiers specified in `meta.identifiers` are expected to be unambiguous and valid.
261-262-`meta.identifiers` contains `v1` attribute which is an attribute set that guarantees backward compatibility of its constituents. Right now it contains copies of all other attributes in `meta.identifiers`.
263-264-### CPE {#sec-meta-identifiers-cpe}
265-266-Common Platform Enumeration (CPE) is a specification maintained by NIST as part of the Security Content Automation Protocol (SCAP). It is used to identify software in National Vulnerabilities Database (NVD, https://nvd.nist.gov) and other vulnerability databases.
267-268-Current version of CPE 2.3 consists of 13 parts:
269-270-```
271-cpe:2.3:a:<vendor>:<product>:<version>:<update>:<edition>:<language>:<sw_edition>:<target_sw>:<target_hw>:<other>
272-```
273-274-Some of them are as follows:
275-276-* *CPE version* - current version of CPE is `2.3`
277-* *part* - usually in Nixpkgs `a` for "application", can also be `o` for "operating system" or `h` for "hardware"
278-* *vendor* - can point to the source of the package, or to Nixpkgs itself
279-* *product* - name of the package
280-* *version* - version of the package
281-* *update* - name of the latest update, can be a patch version for semantically versioned packages
282-* *edition* - any additional specification about the version
283-284-You can find information about all of these attributes in the [official specification](https://csrc.nist.gov/projects/security-content-automation-protocol/specifications/cpe/naming) (heading 5.3.3, pages 11-13).
285-286-Any fields that don't have a value are set to either `-` if the value is not available or `*` when the field can match any value.
287-288-For example, for glibc 2.40.1 CPE would be `cpe:2.3:a:gnu:glibc:2.40:1:*:*:*:*:*:*`.
289-290-#### `meta.identifiers.cpeParts` {#var-meta-identifiers-cpeParts}
291-292-This attribute contains an attribute set of all parts of the CPE for this package. Most of the parts default to `*` (match any value), with some exceptions:
293-294-* `part` defaults to `a` (application), can also be set to `o` for operating systems, for example, Linux kernel, or to `h` for hardware
295-* `vendor` cannot be deduced from other sources, so it must be specified by the package author
296-* `product` defaults to provided derivation's `pname` attribute and must be provided explicitly if `pname` is missing
297-* `version` and `update` have no defaults and should be specified explicitly or using helper functions, when missing, `cpe` attribute will be empty, and all possible guesses using helper functions will be in `possibleCPEs` attribute.
298-299-It is up to the package author to make sure all parts are correct and match expected values in [NVD dictionary](https://nvd.nist.gov/products/cpe). Unknown values can be skipped, which would leave them with the default value of `*`.
300-301-Following functions help with filling out `version` and `update` fields:
302-303-* [`lib.meta.cpeFullVersionWithVendor`](#function-library-lib.meta.cpeFullVersionWithVendor)
304-* [`lib.meta.cpePatchVersionInUpdateWithVendor`](#function-library-lib.meta.cpePatchVersionInUpdateWithVendor)
305-306-For many packages to make CPE available it should be enough to specify only:
307-308-```nix
309-{
310- # ...
311- meta.identifiers.cpeParts = lib.meta.cpePatchVersionInUpdateWithVendor vendor version;
312-}
313-```
314-315-#### `meta.identifiers.cpe` {#var-meta-identifiers-cpe}
316-317-A readonly attribute that concatenates all CPE parts in one string.
318-319-#### `meta.identifiers.possibleCPEs` {#var-meta-identifiers-possibleCPEs}
320-321-A readonly attribute containing the list of guesses for what CPE for this package can look like. It includes all variants of version handling mentioned above. Each item is an attrset with attributes `cpeParts` and `cpe` for each guess.
···248### `lib.sourceTypes.binaryBytecode` {#lib.sourceTypes.binaryBytecode}
249250Code to run on a VM interpreter or JIT compiled into bytecode by a third party. This includes packages which download Java `.jar` files from another source.
00000000000000000000000000000000000000000000000000000000000000000000000
+1-188
lib/meta.nix
···15 assertMsg
16 ;
17 inherit (lib.attrsets) mapAttrs' filterAttrs;
18- inherit (builtins)
19- isString
20- match
21- typeOf
22- elemAt
23- ;
2425in
26rec {
···489 assert assertMsg (match ".*/.*" y == null)
490 "lib.meta.getExe': The second argument \"${y}\" is a nested path with a \"/\" character, but it should just be the name of the executable instead.";
491 "${getBin x}/bin/${y}";
492-493- /**
494- Generate [CPE parts](#var-meta-identifiers-cpeParts) from inputs. Copies `vendor` and `version` to the output, and sets `update` to `*`.
495-496- # Inputs
497-498- `vendor`
499-500- : package's vendor
501-502- `version`
503-504- : package's version
505-506- # Type
507-508- ```
509- cpeFullVersionWithVendor :: string -> string -> AttrSet
510- ```
511-512- # Examples
513- :::{.example}
514- ## `lib.meta.cpeFullVersionWithVendor` usage example
515-516- ```nix
517- lib.meta.cpeFullVersionWithVendor "gnu" "1.2.3"
518- => {
519- vendor = "gnu";
520- version = "1.2.3";
521- update = "*";
522- }
523- ```
524-525- :::
526- :::{.example}
527- ## `lib.meta.cpeFullVersionWithVendor` usage in derivations
528-529- ```nix
530- mkDerivation rec {
531- version = "1.2.3";
532- # ...
533- meta = {
534- # ...
535- identifiers.cpeParts = lib.meta.cpeFullVersionWithVendor "gnu" version;
536- };
537- }
538- ```
539- :::
540- */
541- cpeFullVersionWithVendor = vendor: version: {
542- inherit vendor version;
543- update = "*";
544- };
545-546- /**
547- Alternate version of [`lib.meta.cpePatchVersionInUpdateWithVendor`](#function-library-lib.meta.cpePatchVersionInUpdateWithVendor).
548- If `cpePatchVersionInUpdateWithVendor` succeeds, returns an attribute set with `success` set to `true` and `value` set to the result.
549- Otherwise, `success` is set to `false` and `error` is set to the string representation of the error.
550-551- # Inputs
552-553- `vendor`
554-555- : package's vendor
556-557- `version`
558-559- : package's version
560-561- # Type
562-563- ```
564- tryCPEPatchVersionInUpdateWithVendor :: string -> string -> AttrSet
565- ```
566-567- # Examples
568- :::{.example}
569- ## `lib.meta.tryCPEPatchVersionInUpdateWithVendor` usage example
570-571- ```nix
572- lib.meta.tryCPEPatchVersionInUpdateWithVendor "gnu" "1.2.3"
573- => {
574- success = true;
575- value = {
576- vendor = "gnu";
577- version = "1.2";
578- update = "3";
579- };
580- }
581- ```
582-583- :::
584- :::{.example}
585- ## `lib.meta.cpePatchVersionInUpdateWithVendor` error example
586-587- ```nix
588- lib.meta.tryCPEPatchVersionInUpdateWithVendor "gnu" "5.3p0"
589- => {
590- success = false;
591- error = "version 5.3p0 doesn't match regex `([0-9]+\\.[0-9]+)\\.([0-9]+)`";
592- }
593- ```
594-595- :::
596- */
597- tryCPEPatchVersionInUpdateWithVendor =
598- vendor: version:
599- let
600- regex = "([0-9]+\\.[0-9]+)\\.([0-9]+)";
601- # we have to call toString here in case version is an attrset with __toString attribute
602- versionMatch = builtins.match regex (toString version);
603- in
604- if versionMatch == null then
605- {
606- success = false;
607- error = "version ${version} doesn't match regex `${regex}`";
608- }
609- else
610- {
611- success = true;
612- value = {
613- inherit vendor;
614- version = elemAt versionMatch 0;
615- update = elemAt versionMatch 1;
616- };
617- };
618-619- /**
620- Generate [CPE parts](#var-meta-identifiers-cpeParts) from inputs. Copies `vendor` to the result. When `version` matches `X.Y.Z` where all parts are numerical, sets `version` and `update` fields to `X.Y` and `Z`. Throws an error if the version doesn't match the expected template.
621-622- # Inputs
623-624- `vendor`
625-626- : package's vendor
627-628- `version`
629-630- : package's version
631-632- # Type
633-634- ```
635- cpePatchVersionInUpdateWithVendor :: string -> string -> AttrSet
636- ```
637-638- # Examples
639- :::{.example}
640- ## `lib.meta.cpePatchVersionInUpdateWithVendor` usage example
641-642- ```nix
643- lib.meta.cpePatchVersionInUpdateWithVendor "gnu" "1.2.3"
644- => {
645- vendor = "gnu";
646- version = "1.2";
647- update = "3";
648- }
649- ```
650-651- :::
652- :::{.example}
653- ## `lib.meta.cpePatchVersionInUpdateWithVendor` usage in derivations
654-655- ```nix
656- mkDerivation rec {
657- version = "1.2.3";
658- # ...
659- meta = {
660- # ...
661- identifiers.cpeParts = lib.meta.cpePatchVersionInUpdateWithVendor "gnu" version;
662- };
663- }
664- ```
665-666- :::
667- */
668- cpePatchVersionInUpdateWithVendor =
669- vendor: version:
670- let
671- result = tryCPEPatchVersionInUpdateWithVendor vendor version;
672- in
673- if result.success then result.value else throw result.error;
674}
···15 assertMsg
16 ;
17 inherit (lib.attrsets) mapAttrs' filterAttrs;
18+ inherit (builtins) isString match typeOf;
000001920in
21rec {
···484 assert assertMsg (match ".*/.*" y == null)
485 "lib.meta.getExe': The second argument \"${y}\" is a nested path with a \"/\" character, but it should just be the name of the executable instead.";
486 "${getBin x}/bin/${y}";
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000487}
···11 inherit (lib)
12 all
13 attrNames
14- attrValues
15 concatMapStrings
16 concatMapStringsSep
17 concatStrings
···3839 inherit (lib.meta)
40 availableOn
41- cpeFullVersionWithVendor
42- tryCPEPatchVersionInUpdateWithVendor
43 ;
4445 inherit (lib.generators)
···440 # Used for the original location of the maintainer and team attributes to assist with pings.
441 maintainersPosition = any;
442 teamsPosition = any;
443-444- identifiers = attrs;
445 };
446447 checkMetaAttr =
···575 else
576 validYes;
577578- # Helper functions and declarations to handle identifiers, extracted to reduce allocations
579- hasAllCPEParts = cpeParts: !any isNull (attrValues cpeParts);
580- makeCPE =
581- cpeParts:
582- "cpe:2.3:${cpeParts.part}:${cpeParts.vendor}:${cpeParts.product}:${cpeParts.version}:${cpeParts.update}:${cpeParts.edition}:${cpeParts.sw_edition}:${cpeParts.target_sw}:${cpeParts.target_hw}:${cpeParts.language}:${cpeParts.other}";
583- possibleCPEPartsFuns = [
584- (vendor: version: {
585- success = true;
586- value = cpeFullVersionWithVendor vendor version;
587- })
588- tryCPEPatchVersionInUpdateWithVendor
589- ];
590-591 # The meta attribute is passed in the resulting attribute set,
592 # but it's not part of the actual derivation, i.e., it's not
593 # passed to the builder and is not a dependency. But since we
···651 # if you add a new maintainer or team attribute please ensure that this expectation is still met.
652 maintainers =
653 attrs.meta.maintainers or [ ] ++ concatMap (team: team.members or [ ]) attrs.meta.teams or [ ];
654-655- identifiers =
656- let
657- defaultCPEParts = {
658- part = "a";
659- vendor = null;
660- product = attrs.pname or null;
661- version = null;
662- update = null;
663- edition = "*";
664- sw_edition = "*";
665- target_sw = "*";
666- target_hw = "*";
667- language = "*";
668- other = "*";
669- };
670-671- cpeParts = defaultCPEParts // attrs.meta.identifiers.cpeParts or { };
672- cpe = if hasAllCPEParts cpeParts then makeCPE cpeParts else null;
673-674- possibleCPEs =
675- if cpe != null then
676- [ { inherit cpeParts cpe; } ]
677- else if attrs.meta.identifiers.cpeParts.vendor or null == null || attrs.version or null == null then
678- [ ]
679- else
680- concatMap (
681- f:
682- let
683- result = f attrs.meta.identifiers.cpeParts.vendor attrs.version;
684- # Note that attrs.meta.identifiers.cpeParts at this point can include defaults with user overrides.
685- # Since we can't split them apart, user overrides don't apply to possibleCPEs.
686- guessedParts = cpeParts // result.value;
687- in
688- optional (result.success && (hasAllCPEParts guessedParts)) {
689- cpeParts = guessedParts;
690- cpe = (makeCPE guessedParts);
691- }
692- ) possibleCPEPartsFuns;
693- v1 = { inherit cpeParts cpe possibleCPEs; };
694- in
695- v1
696- // {
697- inherit v1;
698- };
699700 # Expose the result of the checks for everyone to see.
701 unfree = hasUnfreeLicense attrs;
···11 inherit (lib)
12 all
13 attrNames
014 concatMapStrings
15 concatMapStringsSep
16 concatStrings
···3738 inherit (lib.meta)
39 availableOn
0040 ;
4142 inherit (lib.generators)
···437 # Used for the original location of the maintainer and team attributes to assist with pings.
438 maintainersPosition = any;
439 teamsPosition = any;
00440 };
441442 checkMetaAttr =
···570 else
571 validYes;
5720000000000000573 # The meta attribute is passed in the resulting attribute set,
574 # but it's not part of the actual derivation, i.e., it's not
575 # passed to the builder and is not a dependency. But since we
···633 # if you add a new maintainer or team attribute please ensure that this expectation is still met.
634 maintainers =
635 attrs.meta.maintainers or [ ] ++ concatMap (team: team.members or [ ]) attrs.meta.teams or [ ];
000000000000000000000000000000000000000000000636637 # Expose the result of the checks for everyone to see.
638 unfree = hasUnfreeLicense attrs;