Projects STRLCPY syft Commits 7464079a
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    README.md
    skipped 44 lines
    45 45  - Java (jar, ear, war, par, sar, native-image)
    46 46  - JavaScript (npm, yarn)
    47 47  - Jenkins Plugins (jpi, hpi)
     48 +- Nix (outputs in /nix/store)
    48 49  - PHP (composer)
    49 50  - Python (wheel, egg, poetry, requirements.txt)
    50 51  - Red Hat (rpm)
    skipped 619 lines
  • ■ ■ ■ ■
    internal/constants.go
    skipped 5 lines
    6 6   
    7 7   // JSONSchemaVersion is the current schema version output by the JSON encoder
    8 8   // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
    9  - JSONSchemaVersion = "7.1.0"
     9 + JSONSchemaVersion = "7.1.1"
    10 10  )
    11 11   
  • ■ ■ ■ ■ ■
    schema/json/generate.go
    skipped 44 lines
    45 45   Hackage pkg.HackageMetadata
    46 46   Java pkg.JavaMetadata
    47 47   KbPackage pkg.KbPackageMetadata
     48 + Nix pkg.NixStoreMetadata
    48 49   NpmPackage pkg.NpmPackageJSONMetadata
    49 50   NpmPackageLock pkg.NpmPackageLockJSONMetadata
    50 51   MixLock pkg.MixLockMetadata
    skipped 115 lines
  • ■ ■ ■ ■ ■ ■
    schema/json/schema-7.1.1.json
     1 +{
     2 + "$schema": "https://json-schema.org/draft/2020-12/schema",
     3 + "$id": "https://github.com/anchore/syft/syft/formats/syftjson/model/document",
     4 + "$ref": "#/$defs/Document",
     5 + "$defs": {
     6 + "AlpmFileRecord": {
     7 + "properties": {
     8 + "path": {
     9 + "type": "string"
     10 + },
     11 + "type": {
     12 + "type": "string"
     13 + },
     14 + "uid": {
     15 + "type": "string"
     16 + },
     17 + "gid": {
     18 + "type": "string"
     19 + },
     20 + "time": {
     21 + "type": "string",
     22 + "format": "date-time"
     23 + },
     24 + "size": {
     25 + "type": "string"
     26 + },
     27 + "link": {
     28 + "type": "string"
     29 + },
     30 + "digest": {
     31 + "items": {
     32 + "$ref": "#/$defs/Digest"
     33 + },
     34 + "type": "array"
     35 + }
     36 + },
     37 + "type": "object"
     38 + },
     39 + "AlpmMetadata": {
     40 + "properties": {
     41 + "basepackage": {
     42 + "type": "string"
     43 + },
     44 + "package": {
     45 + "type": "string"
     46 + },
     47 + "version": {
     48 + "type": "string"
     49 + },
     50 + "description": {
     51 + "type": "string"
     52 + },
     53 + "architecture": {
     54 + "type": "string"
     55 + },
     56 + "size": {
     57 + "type": "integer"
     58 + },
     59 + "packager": {
     60 + "type": "string"
     61 + },
     62 + "license": {
     63 + "type": "string"
     64 + },
     65 + "url": {
     66 + "type": "string"
     67 + },
     68 + "validation": {
     69 + "type": "string"
     70 + },
     71 + "reason": {
     72 + "type": "integer"
     73 + },
     74 + "files": {
     75 + "items": {
     76 + "$ref": "#/$defs/AlpmFileRecord"
     77 + },
     78 + "type": "array"
     79 + },
     80 + "backup": {
     81 + "items": {
     82 + "$ref": "#/$defs/AlpmFileRecord"
     83 + },
     84 + "type": "array"
     85 + }
     86 + },
     87 + "type": "object",
     88 + "required": [
     89 + "basepackage",
     90 + "package",
     91 + "version",
     92 + "description",
     93 + "architecture",
     94 + "size",
     95 + "packager",
     96 + "license",
     97 + "url",
     98 + "validation",
     99 + "reason",
     100 + "files",
     101 + "backup"
     102 + ]
     103 + },
     104 + "ApkFileRecord": {
     105 + "properties": {
     106 + "path": {
     107 + "type": "string"
     108 + },
     109 + "ownerUid": {
     110 + "type": "string"
     111 + },
     112 + "ownerGid": {
     113 + "type": "string"
     114 + },
     115 + "permissions": {
     116 + "type": "string"
     117 + },
     118 + "digest": {
     119 + "$ref": "#/$defs/Digest"
     120 + }
     121 + },
     122 + "type": "object",
     123 + "required": [
     124 + "path"
     125 + ]
     126 + },
     127 + "ApkMetadata": {
     128 + "properties": {
     129 + "package": {
     130 + "type": "string"
     131 + },
     132 + "originPackage": {
     133 + "type": "string"
     134 + },
     135 + "maintainer": {
     136 + "type": "string"
     137 + },
     138 + "version": {
     139 + "type": "string"
     140 + },
     141 + "license": {
     142 + "type": "string"
     143 + },
     144 + "architecture": {
     145 + "type": "string"
     146 + },
     147 + "url": {
     148 + "type": "string"
     149 + },
     150 + "description": {
     151 + "type": "string"
     152 + },
     153 + "size": {
     154 + "type": "integer"
     155 + },
     156 + "installedSize": {
     157 + "type": "integer"
     158 + },
     159 + "pullDependencies": {
     160 + "items": {
     161 + "type": "string"
     162 + },
     163 + "type": "array"
     164 + },
     165 + "provides": {
     166 + "items": {
     167 + "type": "string"
     168 + },
     169 + "type": "array"
     170 + },
     171 + "pullChecksum": {
     172 + "type": "string"
     173 + },
     174 + "gitCommitOfApkPort": {
     175 + "type": "string"
     176 + },
     177 + "files": {
     178 + "items": {
     179 + "$ref": "#/$defs/ApkFileRecord"
     180 + },
     181 + "type": "array"
     182 + }
     183 + },
     184 + "type": "object",
     185 + "required": [
     186 + "package",
     187 + "originPackage",
     188 + "maintainer",
     189 + "version",
     190 + "license",
     191 + "architecture",
     192 + "url",
     193 + "description",
     194 + "size",
     195 + "installedSize",
     196 + "pullDependencies",
     197 + "provides",
     198 + "pullChecksum",
     199 + "gitCommitOfApkPort",
     200 + "files"
     201 + ]
     202 + },
     203 + "BinaryMetadata": {
     204 + "properties": {
     205 + "matches": {
     206 + "items": {
     207 + "$ref": "#/$defs/ClassifierMatch"
     208 + },
     209 + "type": "array"
     210 + }
     211 + },
     212 + "type": "object",
     213 + "required": [
     214 + "matches"
     215 + ]
     216 + },
     217 + "CargoPackageMetadata": {
     218 + "properties": {
     219 + "name": {
     220 + "type": "string"
     221 + },
     222 + "version": {
     223 + "type": "string"
     224 + },
     225 + "source": {
     226 + "type": "string"
     227 + },
     228 + "checksum": {
     229 + "type": "string"
     230 + },
     231 + "dependencies": {
     232 + "items": {
     233 + "type": "string"
     234 + },
     235 + "type": "array"
     236 + }
     237 + },
     238 + "type": "object",
     239 + "required": [
     240 + "name",
     241 + "version",
     242 + "source",
     243 + "checksum",
     244 + "dependencies"
     245 + ]
     246 + },
     247 + "ClassifierMatch": {
     248 + "properties": {
     249 + "classifier": {
     250 + "type": "string"
     251 + },
     252 + "location": {
     253 + "$ref": "#/$defs/Location"
     254 + }
     255 + },
     256 + "type": "object",
     257 + "required": [
     258 + "classifier",
     259 + "location"
     260 + ]
     261 + },
     262 + "CocoapodsMetadata": {
     263 + "properties": {
     264 + "checksum": {
     265 + "type": "string"
     266 + }
     267 + },
     268 + "type": "object",
     269 + "required": [
     270 + "checksum"
     271 + ]
     272 + },
     273 + "ConanLockMetadata": {
     274 + "properties": {
     275 + "ref": {
     276 + "type": "string"
     277 + },
     278 + "package_id": {
     279 + "type": "string"
     280 + },
     281 + "prev": {
     282 + "type": "string"
     283 + },
     284 + "requires": {
     285 + "type": "string"
     286 + },
     287 + "build_requires": {
     288 + "type": "string"
     289 + },
     290 + "py_requires": {
     291 + "type": "string"
     292 + },
     293 + "options": {
     294 + "patternProperties": {
     295 + ".*": {
     296 + "type": "string"
     297 + }
     298 + },
     299 + "type": "object"
     300 + },
     301 + "path": {
     302 + "type": "string"
     303 + },
     304 + "context": {
     305 + "type": "string"
     306 + }
     307 + },
     308 + "type": "object",
     309 + "required": [
     310 + "ref"
     311 + ]
     312 + },
     313 + "ConanMetadata": {
     314 + "properties": {
     315 + "ref": {
     316 + "type": "string"
     317 + }
     318 + },
     319 + "type": "object",
     320 + "required": [
     321 + "ref"
     322 + ]
     323 + },
     324 + "Coordinates": {
     325 + "properties": {
     326 + "path": {
     327 + "type": "string"
     328 + },
     329 + "layerID": {
     330 + "type": "string"
     331 + }
     332 + },
     333 + "type": "object",
     334 + "required": [
     335 + "path"
     336 + ]
     337 + },
     338 + "DartPubMetadata": {
     339 + "properties": {
     340 + "name": {
     341 + "type": "string"
     342 + },
     343 + "version": {
     344 + "type": "string"
     345 + },
     346 + "hosted_url": {
     347 + "type": "string"
     348 + },
     349 + "vcs_url": {
     350 + "type": "string"
     351 + }
     352 + },
     353 + "type": "object",
     354 + "required": [
     355 + "name",
     356 + "version"
     357 + ]
     358 + },
     359 + "Descriptor": {
     360 + "properties": {
     361 + "name": {
     362 + "type": "string"
     363 + },
     364 + "version": {
     365 + "type": "string"
     366 + },
     367 + "configuration": true
     368 + },
     369 + "type": "object",
     370 + "required": [
     371 + "name",
     372 + "version"
     373 + ]
     374 + },
     375 + "Digest": {
     376 + "properties": {
     377 + "algorithm": {
     378 + "type": "string"
     379 + },
     380 + "value": {
     381 + "type": "string"
     382 + }
     383 + },
     384 + "type": "object",
     385 + "required": [
     386 + "algorithm",
     387 + "value"
     388 + ]
     389 + },
     390 + "Document": {
     391 + "properties": {
     392 + "artifacts": {
     393 + "items": {
     394 + "$ref": "#/$defs/Package"
     395 + },
     396 + "type": "array"
     397 + },
     398 + "artifactRelationships": {
     399 + "items": {
     400 + "$ref": "#/$defs/Relationship"
     401 + },
     402 + "type": "array"
     403 + },
     404 + "files": {
     405 + "items": {
     406 + "$ref": "#/$defs/File"
     407 + },
     408 + "type": "array"
     409 + },
     410 + "secrets": {
     411 + "items": {
     412 + "$ref": "#/$defs/Secrets"
     413 + },
     414 + "type": "array"
     415 + },
     416 + "source": {
     417 + "$ref": "#/$defs/Source"
     418 + },
     419 + "distro": {
     420 + "$ref": "#/$defs/LinuxRelease"
     421 + },
     422 + "descriptor": {
     423 + "$ref": "#/$defs/Descriptor"
     424 + },
     425 + "schema": {
     426 + "$ref": "#/$defs/Schema"
     427 + }
     428 + },
     429 + "type": "object",
     430 + "required": [
     431 + "artifacts",
     432 + "artifactRelationships",
     433 + "source",
     434 + "distro",
     435 + "descriptor",
     436 + "schema"
     437 + ]
     438 + },
     439 + "DotnetDepsMetadata": {
     440 + "properties": {
     441 + "name": {
     442 + "type": "string"
     443 + },
     444 + "version": {
     445 + "type": "string"
     446 + },
     447 + "path": {
     448 + "type": "string"
     449 + },
     450 + "sha512": {
     451 + "type": "string"
     452 + },
     453 + "hashPath": {
     454 + "type": "string"
     455 + }
     456 + },
     457 + "type": "object",
     458 + "required": [
     459 + "name",
     460 + "version",
     461 + "path",
     462 + "sha512",
     463 + "hashPath"
     464 + ]
     465 + },
     466 + "DpkgFileRecord": {
     467 + "properties": {
     468 + "path": {
     469 + "type": "string"
     470 + },
     471 + "digest": {
     472 + "$ref": "#/$defs/Digest"
     473 + },
     474 + "isConfigFile": {
     475 + "type": "boolean"
     476 + }
     477 + },
     478 + "type": "object",
     479 + "required": [
     480 + "path",
     481 + "isConfigFile"
     482 + ]
     483 + },
     484 + "DpkgMetadata": {
     485 + "properties": {
     486 + "package": {
     487 + "type": "string"
     488 + },
     489 + "source": {
     490 + "type": "string"
     491 + },
     492 + "version": {
     493 + "type": "string"
     494 + },
     495 + "sourceVersion": {
     496 + "type": "string"
     497 + },
     498 + "architecture": {
     499 + "type": "string"
     500 + },
     501 + "maintainer": {
     502 + "type": "string"
     503 + },
     504 + "installedSize": {
     505 + "type": "integer"
     506 + },
     507 + "files": {
     508 + "items": {
     509 + "$ref": "#/$defs/DpkgFileRecord"
     510 + },
     511 + "type": "array"
     512 + }
     513 + },
     514 + "type": "object",
     515 + "required": [
     516 + "package",
     517 + "source",
     518 + "version",
     519 + "sourceVersion",
     520 + "architecture",
     521 + "maintainer",
     522 + "installedSize",
     523 + "files"
     524 + ]
     525 + },
     526 + "File": {
     527 + "properties": {
     528 + "id": {
     529 + "type": "string"
     530 + },
     531 + "location": {
     532 + "$ref": "#/$defs/Coordinates"
     533 + },
     534 + "metadata": {
     535 + "$ref": "#/$defs/FileMetadataEntry"
     536 + },
     537 + "contents": {
     538 + "type": "string"
     539 + },
     540 + "digests": {
     541 + "items": {
     542 + "$ref": "#/$defs/Digest"
     543 + },
     544 + "type": "array"
     545 + }
     546 + },
     547 + "type": "object",
     548 + "required": [
     549 + "id",
     550 + "location"
     551 + ]
     552 + },
     553 + "FileMetadataEntry": {
     554 + "properties": {
     555 + "mode": {
     556 + "type": "integer"
     557 + },
     558 + "type": {
     559 + "type": "string"
     560 + },
     561 + "linkDestination": {
     562 + "type": "string"
     563 + },
     564 + "userID": {
     565 + "type": "integer"
     566 + },
     567 + "groupID": {
     568 + "type": "integer"
     569 + },
     570 + "mimeType": {
     571 + "type": "string"
     572 + }
     573 + },
     574 + "type": "object",
     575 + "required": [
     576 + "mode",
     577 + "type",
     578 + "userID",
     579 + "groupID",
     580 + "mimeType"
     581 + ]
     582 + },
     583 + "GemMetadata": {
     584 + "properties": {
     585 + "name": {
     586 + "type": "string"
     587 + },
     588 + "version": {
     589 + "type": "string"
     590 + },
     591 + "files": {
     592 + "items": {
     593 + "type": "string"
     594 + },
     595 + "type": "array"
     596 + },
     597 + "authors": {
     598 + "items": {
     599 + "type": "string"
     600 + },
     601 + "type": "array"
     602 + },
     603 + "licenses": {
     604 + "items": {
     605 + "type": "string"
     606 + },
     607 + "type": "array"
     608 + },
     609 + "homepage": {
     610 + "type": "string"
     611 + }
     612 + },
     613 + "type": "object",
     614 + "required": [
     615 + "name",
     616 + "version"
     617 + ]
     618 + },
     619 + "GolangBinMetadata": {
     620 + "properties": {
     621 + "goBuildSettings": {
     622 + "patternProperties": {
     623 + ".*": {
     624 + "type": "string"
     625 + }
     626 + },
     627 + "type": "object"
     628 + },
     629 + "goCompiledVersion": {
     630 + "type": "string"
     631 + },
     632 + "architecture": {
     633 + "type": "string"
     634 + },
     635 + "h1Digest": {
     636 + "type": "string"
     637 + },
     638 + "mainModule": {
     639 + "type": "string"
     640 + }
     641 + },
     642 + "type": "object",
     643 + "required": [
     644 + "goCompiledVersion",
     645 + "architecture"
     646 + ]
     647 + },
     648 + "GolangModMetadata": {
     649 + "properties": {
     650 + "h1Digest": {
     651 + "type": "string"
     652 + }
     653 + },
     654 + "type": "object"
     655 + },
     656 + "HackageMetadata": {
     657 + "properties": {
     658 + "name": {
     659 + "type": "string"
     660 + },
     661 + "version": {
     662 + "type": "string"
     663 + },
     664 + "pkgHash": {
     665 + "type": "string"
     666 + },
     667 + "snapshotURL": {
     668 + "type": "string"
     669 + }
     670 + },
     671 + "type": "object",
     672 + "required": [
     673 + "name",
     674 + "version"
     675 + ]
     676 + },
     677 + "IDLikes": {
     678 + "items": {
     679 + "type": "string"
     680 + },
     681 + "type": "array"
     682 + },
     683 + "JavaManifest": {
     684 + "properties": {
     685 + "main": {
     686 + "patternProperties": {
     687 + ".*": {
     688 + "type": "string"
     689 + }
     690 + },
     691 + "type": "object"
     692 + },
     693 + "namedSections": {
     694 + "patternProperties": {
     695 + ".*": {
     696 + "patternProperties": {
     697 + ".*": {
     698 + "type": "string"
     699 + }
     700 + },
     701 + "type": "object"
     702 + }
     703 + },
     704 + "type": "object"
     705 + }
     706 + },
     707 + "type": "object"
     708 + },
     709 + "JavaMetadata": {
     710 + "properties": {
     711 + "virtualPath": {
     712 + "type": "string"
     713 + },
     714 + "manifest": {
     715 + "$ref": "#/$defs/JavaManifest"
     716 + },
     717 + "pomProperties": {
     718 + "$ref": "#/$defs/PomProperties"
     719 + },
     720 + "pomProject": {
     721 + "$ref": "#/$defs/PomProject"
     722 + },
     723 + "digest": {
     724 + "items": {
     725 + "$ref": "#/$defs/Digest"
     726 + },
     727 + "type": "array"
     728 + }
     729 + },
     730 + "type": "object",
     731 + "required": [
     732 + "virtualPath"
     733 + ]
     734 + },
     735 + "KbPackageMetadata": {
     736 + "properties": {
     737 + "product_id": {
     738 + "type": "string"
     739 + },
     740 + "kb": {
     741 + "type": "string"
     742 + }
     743 + },
     744 + "type": "object",
     745 + "required": [
     746 + "product_id",
     747 + "kb"
     748 + ]
     749 + },
     750 + "LinuxRelease": {
     751 + "properties": {
     752 + "prettyName": {
     753 + "type": "string"
     754 + },
     755 + "name": {
     756 + "type": "string"
     757 + },
     758 + "id": {
     759 + "type": "string"
     760 + },
     761 + "idLike": {
     762 + "$ref": "#/$defs/IDLikes"
     763 + },
     764 + "version": {
     765 + "type": "string"
     766 + },
     767 + "versionID": {
     768 + "type": "string"
     769 + },
     770 + "versionCodename": {
     771 + "type": "string"
     772 + },
     773 + "buildID": {
     774 + "type": "string"
     775 + },
     776 + "imageID": {
     777 + "type": "string"
     778 + },
     779 + "imageVersion": {
     780 + "type": "string"
     781 + },
     782 + "variant": {
     783 + "type": "string"
     784 + },
     785 + "variantID": {
     786 + "type": "string"
     787 + },
     788 + "homeURL": {
     789 + "type": "string"
     790 + },
     791 + "supportURL": {
     792 + "type": "string"
     793 + },
     794 + "bugReportURL": {
     795 + "type": "string"
     796 + },
     797 + "privacyPolicyURL": {
     798 + "type": "string"
     799 + },
     800 + "cpeName": {
     801 + "type": "string"
     802 + },
     803 + "supportEnd": {
     804 + "type": "string"
     805 + }
     806 + },
     807 + "type": "object"
     808 + },
     809 + "Location": {
     810 + "properties": {
     811 + "path": {
     812 + "type": "string"
     813 + },
     814 + "layerID": {
     815 + "type": "string"
     816 + },
     817 + "virtualPath": {
     818 + "type": "string"
     819 + }
     820 + },
     821 + "type": "object",
     822 + "required": [
     823 + "path"
     824 + ]
     825 + },
     826 + "MixLockMetadata": {
     827 + "properties": {
     828 + "name": {
     829 + "type": "string"
     830 + },
     831 + "version": {
     832 + "type": "string"
     833 + },
     834 + "pkgHash": {
     835 + "type": "string"
     836 + },
     837 + "pkgHashExt": {
     838 + "type": "string"
     839 + }
     840 + },
     841 + "type": "object",
     842 + "required": [
     843 + "name",
     844 + "version",
     845 + "pkgHash",
     846 + "pkgHashExt"
     847 + ]
     848 + },
     849 + "NixStoreMetadata": {
     850 + "properties": {
     851 + "outputHash": {
     852 + "type": "string"
     853 + },
     854 + "output": {
     855 + "type": "string"
     856 + },
     857 + "files": {
     858 + "items": {
     859 + "type": "string"
     860 + },
     861 + "type": "array"
     862 + }
     863 + },
     864 + "type": "object",
     865 + "required": [
     866 + "outputHash",
     867 + "files"
     868 + ]
     869 + },
     870 + "NpmPackageJSONMetadata": {
     871 + "properties": {
     872 + "name": {
     873 + "type": "string"
     874 + },
     875 + "version": {
     876 + "type": "string"
     877 + },
     878 + "author": {
     879 + "type": "string"
     880 + },
     881 + "licenses": {
     882 + "items": {
     883 + "type": "string"
     884 + },
     885 + "type": "array"
     886 + },
     887 + "homepage": {
     888 + "type": "string"
     889 + },
     890 + "description": {
     891 + "type": "string"
     892 + },
     893 + "url": {
     894 + "type": "string"
     895 + },
     896 + "private": {
     897 + "type": "boolean"
     898 + }
     899 + },
     900 + "type": "object",
     901 + "required": [
     902 + "name",
     903 + "version",
     904 + "author",
     905 + "licenses",
     906 + "homepage",
     907 + "description",
     908 + "url",
     909 + "private"
     910 + ]
     911 + },
     912 + "NpmPackageLockJSONMetadata": {
     913 + "properties": {
     914 + "resolved": {
     915 + "type": "string"
     916 + },
     917 + "integrity": {
     918 + "type": "string"
     919 + }
     920 + },
     921 + "type": "object",
     922 + "required": [
     923 + "resolved",
     924 + "integrity"
     925 + ]
     926 + },
     927 + "Package": {
     928 + "properties": {
     929 + "id": {
     930 + "type": "string"
     931 + },
     932 + "name": {
     933 + "type": "string"
     934 + },
     935 + "version": {
     936 + "type": "string"
     937 + },
     938 + "type": {
     939 + "type": "string"
     940 + },
     941 + "foundBy": {
     942 + "type": "string"
     943 + },
     944 + "locations": {
     945 + "items": {
     946 + "$ref": "#/$defs/Coordinates"
     947 + },
     948 + "type": "array"
     949 + },
     950 + "licenses": {
     951 + "items": {
     952 + "type": "string"
     953 + },
     954 + "type": "array"
     955 + },
     956 + "language": {
     957 + "type": "string"
     958 + },
     959 + "cpes": {
     960 + "items": {
     961 + "type": "string"
     962 + },
     963 + "type": "array"
     964 + },
     965 + "purl": {
     966 + "type": "string"
     967 + },
     968 + "metadataType": {
     969 + "type": "string"
     970 + },
     971 + "metadata": {
     972 + "anyOf": [
     973 + {
     974 + "type": "null"
     975 + },
     976 + {
     977 + "$ref": "#/$defs/AlpmMetadata"
     978 + },
     979 + {
     980 + "$ref": "#/$defs/ApkMetadata"
     981 + },
     982 + {
     983 + "$ref": "#/$defs/BinaryMetadata"
     984 + },
     985 + {
     986 + "$ref": "#/$defs/CargoPackageMetadata"
     987 + },
     988 + {
     989 + "$ref": "#/$defs/CocoapodsMetadata"
     990 + },
     991 + {
     992 + "$ref": "#/$defs/ConanLockMetadata"
     993 + },
     994 + {
     995 + "$ref": "#/$defs/ConanMetadata"
     996 + },
     997 + {
     998 + "$ref": "#/$defs/DartPubMetadata"
     999 + },
     1000 + {
     1001 + "$ref": "#/$defs/DotnetDepsMetadata"
     1002 + },
     1003 + {
     1004 + "$ref": "#/$defs/DpkgMetadata"
     1005 + },
     1006 + {
     1007 + "$ref": "#/$defs/GemMetadata"
     1008 + },
     1009 + {
     1010 + "$ref": "#/$defs/GolangBinMetadata"
     1011 + },
     1012 + {
     1013 + "$ref": "#/$defs/GolangModMetadata"
     1014 + },
     1015 + {
     1016 + "$ref": "#/$defs/HackageMetadata"
     1017 + },
     1018 + {
     1019 + "$ref": "#/$defs/JavaMetadata"
     1020 + },
     1021 + {
     1022 + "$ref": "#/$defs/KbPackageMetadata"
     1023 + },
     1024 + {
     1025 + "$ref": "#/$defs/MixLockMetadata"
     1026 + },
     1027 + {
     1028 + "$ref": "#/$defs/NixStoreMetadata"
     1029 + },
     1030 + {
     1031 + "$ref": "#/$defs/NpmPackageJSONMetadata"
     1032 + },
     1033 + {
     1034 + "$ref": "#/$defs/NpmPackageLockJSONMetadata"
     1035 + },
     1036 + {
     1037 + "$ref": "#/$defs/PhpComposerJSONMetadata"
     1038 + },
     1039 + {
     1040 + "$ref": "#/$defs/PortageMetadata"
     1041 + },
     1042 + {
     1043 + "$ref": "#/$defs/PythonPackageMetadata"
     1044 + },
     1045 + {
     1046 + "$ref": "#/$defs/PythonPipfileLockMetadata"
     1047 + },
     1048 + {
     1049 + "$ref": "#/$defs/RebarLockMetadata"
     1050 + },
     1051 + {
     1052 + "$ref": "#/$defs/RpmMetadata"
     1053 + }
     1054 + ]
     1055 + }
     1056 + },
     1057 + "type": "object",
     1058 + "required": [
     1059 + "id",
     1060 + "name",
     1061 + "version",
     1062 + "type",
     1063 + "foundBy",
     1064 + "locations",
     1065 + "licenses",
     1066 + "language",
     1067 + "cpes",
     1068 + "purl"
     1069 + ]
     1070 + },
     1071 + "PhpComposerAuthors": {
     1072 + "properties": {
     1073 + "name": {
     1074 + "type": "string"
     1075 + },
     1076 + "email": {
     1077 + "type": "string"
     1078 + },
     1079 + "homepage": {
     1080 + "type": "string"
     1081 + }
     1082 + },
     1083 + "type": "object",
     1084 + "required": [
     1085 + "name"
     1086 + ]
     1087 + },
     1088 + "PhpComposerExternalReference": {
     1089 + "properties": {
     1090 + "type": {
     1091 + "type": "string"
     1092 + },
     1093 + "url": {
     1094 + "type": "string"
     1095 + },
     1096 + "reference": {
     1097 + "type": "string"
     1098 + },
     1099 + "shasum": {
     1100 + "type": "string"
     1101 + }
     1102 + },
     1103 + "type": "object",
     1104 + "required": [
     1105 + "type",
     1106 + "url",
     1107 + "reference"
     1108 + ]
     1109 + },
     1110 + "PhpComposerJSONMetadata": {
     1111 + "properties": {
     1112 + "name": {
     1113 + "type": "string"
     1114 + },
     1115 + "version": {
     1116 + "type": "string"
     1117 + },
     1118 + "source": {
     1119 + "$ref": "#/$defs/PhpComposerExternalReference"
     1120 + },
     1121 + "dist": {
     1122 + "$ref": "#/$defs/PhpComposerExternalReference"
     1123 + },
     1124 + "require": {
     1125 + "patternProperties": {
     1126 + ".*": {
     1127 + "type": "string"
     1128 + }
     1129 + },
     1130 + "type": "object"
     1131 + },
     1132 + "provide": {
     1133 + "patternProperties": {
     1134 + ".*": {
     1135 + "type": "string"
     1136 + }
     1137 + },
     1138 + "type": "object"
     1139 + },
     1140 + "require-dev": {
     1141 + "patternProperties": {
     1142 + ".*": {
     1143 + "type": "string"
     1144 + }
     1145 + },
     1146 + "type": "object"
     1147 + },
     1148 + "suggest": {
     1149 + "patternProperties": {
     1150 + ".*": {
     1151 + "type": "string"
     1152 + }
     1153 + },
     1154 + "type": "object"
     1155 + },
     1156 + "type": {
     1157 + "type": "string"
     1158 + },
     1159 + "notification-url": {
     1160 + "type": "string"
     1161 + },
     1162 + "bin": {
     1163 + "items": {
     1164 + "type": "string"
     1165 + },
     1166 + "type": "array"
     1167 + },
     1168 + "license": {
     1169 + "items": {
     1170 + "type": "string"
     1171 + },
     1172 + "type": "array"
     1173 + },
     1174 + "authors": {
     1175 + "items": {
     1176 + "$ref": "#/$defs/PhpComposerAuthors"
     1177 + },
     1178 + "type": "array"
     1179 + },
     1180 + "description": {
     1181 + "type": "string"
     1182 + },
     1183 + "homepage": {
     1184 + "type": "string"
     1185 + },
     1186 + "keywords": {
     1187 + "items": {
     1188 + "type": "string"
     1189 + },
     1190 + "type": "array"
     1191 + },
     1192 + "time": {
     1193 + "type": "string"
     1194 + }
     1195 + },
     1196 + "type": "object",
     1197 + "required": [
     1198 + "name",
     1199 + "version",
     1200 + "source",
     1201 + "dist"
     1202 + ]
     1203 + },
     1204 + "PomParent": {
     1205 + "properties": {
     1206 + "groupId": {
     1207 + "type": "string"
     1208 + },
     1209 + "artifactId": {
     1210 + "type": "string"
     1211 + },
     1212 + "version": {
     1213 + "type": "string"
     1214 + }
     1215 + },
     1216 + "type": "object",
     1217 + "required": [
     1218 + "groupId",
     1219 + "artifactId",
     1220 + "version"
     1221 + ]
     1222 + },
     1223 + "PomProject": {
     1224 + "properties": {
     1225 + "path": {
     1226 + "type": "string"
     1227 + },
     1228 + "parent": {
     1229 + "$ref": "#/$defs/PomParent"
     1230 + },
     1231 + "groupId": {
     1232 + "type": "string"
     1233 + },
     1234 + "artifactId": {
     1235 + "type": "string"
     1236 + },
     1237 + "version": {
     1238 + "type": "string"
     1239 + },
     1240 + "name": {
     1241 + "type": "string"
     1242 + },
     1243 + "description": {
     1244 + "type": "string"
     1245 + },
     1246 + "url": {
     1247 + "type": "string"
     1248 + }
     1249 + },
     1250 + "type": "object",
     1251 + "required": [
     1252 + "path",
     1253 + "groupId",
     1254 + "artifactId",
     1255 + "version",
     1256 + "name"
     1257 + ]
     1258 + },
     1259 + "PomProperties": {
     1260 + "properties": {
     1261 + "path": {
     1262 + "type": "string"
     1263 + },
     1264 + "name": {
     1265 + "type": "string"
     1266 + },
     1267 + "groupId": {
     1268 + "type": "string"
     1269 + },
     1270 + "artifactId": {
     1271 + "type": "string"
     1272 + },
     1273 + "version": {
     1274 + "type": "string"
     1275 + },
     1276 + "extraFields": {
     1277 + "patternProperties": {
     1278 + ".*": {
     1279 + "type": "string"
     1280 + }
     1281 + },
     1282 + "type": "object"
     1283 + }
     1284 + },
     1285 + "type": "object",
     1286 + "required": [
     1287 + "path",
     1288 + "name",
     1289 + "groupId",
     1290 + "artifactId",
     1291 + "version"
     1292 + ]
     1293 + },
     1294 + "PortageFileRecord": {
     1295 + "properties": {
     1296 + "path": {
     1297 + "type": "string"
     1298 + },
     1299 + "digest": {
     1300 + "$ref": "#/$defs/Digest"
     1301 + }
     1302 + },
     1303 + "type": "object",
     1304 + "required": [
     1305 + "path"
     1306 + ]
     1307 + },
     1308 + "PortageMetadata": {
     1309 + "properties": {
     1310 + "installedSize": {
     1311 + "type": "integer"
     1312 + },
     1313 + "files": {
     1314 + "items": {
     1315 + "$ref": "#/$defs/PortageFileRecord"
     1316 + },
     1317 + "type": "array"
     1318 + }
     1319 + },
     1320 + "type": "object",
     1321 + "required": [
     1322 + "installedSize",
     1323 + "files"
     1324 + ]
     1325 + },
     1326 + "PythonDirectURLOriginInfo": {
     1327 + "properties": {
     1328 + "url": {
     1329 + "type": "string"
     1330 + },
     1331 + "commitId": {
     1332 + "type": "string"
     1333 + },
     1334 + "vcs": {
     1335 + "type": "string"
     1336 + }
     1337 + },
     1338 + "type": "object",
     1339 + "required": [
     1340 + "url"
     1341 + ]
     1342 + },
     1343 + "PythonFileDigest": {
     1344 + "properties": {
     1345 + "algorithm": {
     1346 + "type": "string"
     1347 + },
     1348 + "value": {
     1349 + "type": "string"
     1350 + }
     1351 + },
     1352 + "type": "object",
     1353 + "required": [
     1354 + "algorithm",
     1355 + "value"
     1356 + ]
     1357 + },
     1358 + "PythonFileRecord": {
     1359 + "properties": {
     1360 + "path": {
     1361 + "type": "string"
     1362 + },
     1363 + "digest": {
     1364 + "$ref": "#/$defs/PythonFileDigest"
     1365 + },
     1366 + "size": {
     1367 + "type": "string"
     1368 + }
     1369 + },
     1370 + "type": "object",
     1371 + "required": [
     1372 + "path"
     1373 + ]
     1374 + },
     1375 + "PythonPackageMetadata": {
     1376 + "properties": {
     1377 + "name": {
     1378 + "type": "string"
     1379 + },
     1380 + "version": {
     1381 + "type": "string"
     1382 + },
     1383 + "license": {
     1384 + "type": "string"
     1385 + },
     1386 + "author": {
     1387 + "type": "string"
     1388 + },
     1389 + "authorEmail": {
     1390 + "type": "string"
     1391 + },
     1392 + "platform": {
     1393 + "type": "string"
     1394 + },
     1395 + "files": {
     1396 + "items": {
     1397 + "$ref": "#/$defs/PythonFileRecord"
     1398 + },
     1399 + "type": "array"
     1400 + },
     1401 + "sitePackagesRootPath": {
     1402 + "type": "string"
     1403 + },
     1404 + "topLevelPackages": {
     1405 + "items": {
     1406 + "type": "string"
     1407 + },
     1408 + "type": "array"
     1409 + },
     1410 + "directUrlOrigin": {
     1411 + "$ref": "#/$defs/PythonDirectURLOriginInfo"
     1412 + }
     1413 + },
     1414 + "type": "object",
     1415 + "required": [
     1416 + "name",
     1417 + "version",
     1418 + "license",
     1419 + "author",
     1420 + "authorEmail",
     1421 + "platform",
     1422 + "sitePackagesRootPath"
     1423 + ]
     1424 + },
     1425 + "PythonPipfileLockMetadata": {
     1426 + "properties": {
     1427 + "hashes": {
     1428 + "items": {
     1429 + "type": "string"
     1430 + },
     1431 + "type": "array"
     1432 + },
     1433 + "index": {
     1434 + "type": "string"
     1435 + }
     1436 + },
     1437 + "type": "object",
     1438 + "required": [
     1439 + "hashes",
     1440 + "index"
     1441 + ]
     1442 + },
     1443 + "RebarLockMetadata": {
     1444 + "properties": {
     1445 + "name": {
     1446 + "type": "string"
     1447 + },
     1448 + "version": {
     1449 + "type": "string"
     1450 + },
     1451 + "pkgHash": {
     1452 + "type": "string"
     1453 + },
     1454 + "pkgHashExt": {
     1455 + "type": "string"
     1456 + }
     1457 + },
     1458 + "type": "object",
     1459 + "required": [
     1460 + "name",
     1461 + "version",
     1462 + "pkgHash",
     1463 + "pkgHashExt"
     1464 + ]
     1465 + },
     1466 + "Relationship": {
     1467 + "properties": {
     1468 + "parent": {
     1469 + "type": "string"
     1470 + },
     1471 + "child": {
     1472 + "type": "string"
     1473 + },
     1474 + "type": {
     1475 + "type": "string"
     1476 + },
     1477 + "metadata": true
     1478 + },
     1479 + "type": "object",
     1480 + "required": [
     1481 + "parent",
     1482 + "child",
     1483 + "type"
     1484 + ]
     1485 + },
     1486 + "RpmMetadata": {
     1487 + "properties": {
     1488 + "name": {
     1489 + "type": "string"
     1490 + },
     1491 + "version": {
     1492 + "type": "string"
     1493 + },
     1494 + "epoch": {
     1495 + "oneOf": [
     1496 + {
     1497 + "type": "integer"
     1498 + },
     1499 + {
     1500 + "type": "null"
     1501 + }
     1502 + ]
     1503 + },
     1504 + "architecture": {
     1505 + "type": "string"
     1506 + },
     1507 + "release": {
     1508 + "type": "string"
     1509 + },
     1510 + "sourceRpm": {
     1511 + "type": "string"
     1512 + },
     1513 + "size": {
     1514 + "type": "integer"
     1515 + },
     1516 + "license": {
     1517 + "type": "string"
     1518 + },
     1519 + "vendor": {
     1520 + "type": "string"
     1521 + },
     1522 + "modularityLabel": {
     1523 + "type": "string"
     1524 + },
     1525 + "files": {
     1526 + "items": {
     1527 + "$ref": "#/$defs/RpmdbFileRecord"
     1528 + },
     1529 + "type": "array"
     1530 + }
     1531 + },
     1532 + "type": "object",
     1533 + "required": [
     1534 + "name",
     1535 + "version",
     1536 + "epoch",
     1537 + "architecture",
     1538 + "release",
     1539 + "sourceRpm",
     1540 + "size",
     1541 + "license",
     1542 + "vendor",
     1543 + "modularityLabel",
     1544 + "files"
     1545 + ]
     1546 + },
     1547 + "RpmdbFileRecord": {
     1548 + "properties": {
     1549 + "path": {
     1550 + "type": "string"
     1551 + },
     1552 + "mode": {
     1553 + "type": "integer"
     1554 + },
     1555 + "size": {
     1556 + "type": "integer"
     1557 + },
     1558 + "digest": {
     1559 + "$ref": "#/$defs/Digest"
     1560 + },
     1561 + "userName": {
     1562 + "type": "string"
     1563 + },
     1564 + "groupName": {
     1565 + "type": "string"
     1566 + },
     1567 + "flags": {
     1568 + "type": "string"
     1569 + }
     1570 + },
     1571 + "type": "object",
     1572 + "required": [
     1573 + "path",
     1574 + "mode",
     1575 + "size",
     1576 + "digest",
     1577 + "userName",
     1578 + "groupName",
     1579 + "flags"
     1580 + ]
     1581 + },
     1582 + "Schema": {
     1583 + "properties": {
     1584 + "version": {
     1585 + "type": "string"
     1586 + },
     1587 + "url": {
     1588 + "type": "string"
     1589 + }
     1590 + },
     1591 + "type": "object",
     1592 + "required": [
     1593 + "version",
     1594 + "url"
     1595 + ]
     1596 + },
     1597 + "SearchResult": {
     1598 + "properties": {
     1599 + "classification": {
     1600 + "type": "string"
     1601 + },
     1602 + "lineNumber": {
     1603 + "type": "integer"
     1604 + },
     1605 + "lineOffset": {
     1606 + "type": "integer"
     1607 + },
     1608 + "seekPosition": {
     1609 + "type": "integer"
     1610 + },
     1611 + "length": {
     1612 + "type": "integer"
     1613 + },
     1614 + "value": {
     1615 + "type": "string"
     1616 + }
     1617 + },
     1618 + "type": "object",
     1619 + "required": [
     1620 + "classification",
     1621 + "lineNumber",
     1622 + "lineOffset",
     1623 + "seekPosition",
     1624 + "length"
     1625 + ]
     1626 + },
     1627 + "Secrets": {
     1628 + "properties": {
     1629 + "location": {
     1630 + "$ref": "#/$defs/Coordinates"
     1631 + },
     1632 + "secrets": {
     1633 + "items": {
     1634 + "$ref": "#/$defs/SearchResult"
     1635 + },
     1636 + "type": "array"
     1637 + }
     1638 + },
     1639 + "type": "object",
     1640 + "required": [
     1641 + "location",
     1642 + "secrets"
     1643 + ]
     1644 + },
     1645 + "Source": {
     1646 + "properties": {
     1647 + "id": {
     1648 + "type": "string"
     1649 + },
     1650 + "type": {
     1651 + "type": "string"
     1652 + },
     1653 + "target": true
     1654 + },
     1655 + "type": "object",
     1656 + "required": [
     1657 + "id",
     1658 + "type",
     1659 + "target"
     1660 + ]
     1661 + }
     1662 + }
     1663 +}
     1664 + 
  • ■ ■ ■ ■ ■ ■
    syft/formats/common/spdxhelpers/source_info.go
    skipped 44 lines
    45 45   answer = "acquired package info from cabal or stack manifest files"
    46 46   case pkg.HexPkg:
    47 47   answer = "acquired package info from rebar3 or mix manifest file"
     48 + case pkg.NixPkg:
     49 + answer = "acquired package info from nix store path"
    48 50   default:
    49 51   answer = "acquired package info from the following paths"
    50 52   }
    skipped 11 lines
  • ■ ■ ■ ■ ■ ■
    syft/formats/common/spdxhelpers/source_info_test.go
    skipped 198 lines
    199 199   "from rebar3 or mix manifest file",
    200 200   },
    201 201   },
     202 + {
     203 + input: pkg.Package{
     204 + Type: pkg.NixPkg,
     205 + },
     206 + expected: []string{
     207 + "from nix store path",
     208 + },
     209 + },
    202 210   }
    203 211   var pkgTypes []pkg.Type
    204 212   for _, test := range tests {
    skipped 13 lines
  • ■ ■ ■ ■ ■ ■
    syft/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden
    skipped 88 lines
    89 89   }
    90 90   },
    91 91   "schema": {
    92  - "version": "7.1.0",
    93  - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.0.json"
     92 + "version": "7.1.1",
     93 + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json"
    94 94   }
    95 95  }
    96 96   
  • ■ ■ ■ ■ ■ ■
    syft/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden
    skipped 184 lines
    185 185   }
    186 186   },
    187 187   "schema": {
    188  - "version": "7.1.0",
    189  - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.0.json"
     188 + "version": "7.1.1",
     189 + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json"
    190 190   }
    191 191  }
    192 192   
  • ■ ■ ■ ■ ■ ■
    syft/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden
    skipped 111 lines
    112 112   }
    113 113   },
    114 114   "schema": {
    115  - "version": "7.1.0",
    116  - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.0.json"
     115 + "version": "7.1.1",
     116 + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json"
    117 117   }
    118 118  }
    119 119   
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/cataloger.go
    skipped 22 lines
    23 23   "github.com/anchore/syft/syft/pkg/cataloger/haskell"
    24 24   "github.com/anchore/syft/syft/pkg/cataloger/java"
    25 25   "github.com/anchore/syft/syft/pkg/cataloger/javascript"
     26 + "github.com/anchore/syft/syft/pkg/cataloger/nix"
    26 27   "github.com/anchore/syft/syft/pkg/cataloger/php"
    27 28   "github.com/anchore/syft/syft/pkg/cataloger/portage"
    28 29   "github.com/anchore/syft/syft/pkg/cataloger/python"
    skipped 22 lines
    51 52   golang.NewGoModuleBinaryCataloger(cfg.Go()),
    52 53   dotnet.NewDotnetDepsCataloger(),
    53 54   portage.NewPortageCataloger(),
     55 + nix.NewStoreCataloger(),
    54 56   sbom.NewSBOMCataloger(),
    55 57   binary.NewCataloger(),
    56 58   }, cfg.Catalogers)
    skipped 28 lines
    85 87   binary.NewCataloger(),
    86 88   elixir.NewMixLockCataloger(),
    87 89   erlang.NewRebarLockCataloger(),
     90 + nix.NewStoreCataloger(),
    88 91   }, cfg.Catalogers)
    89 92  }
    90 93   
    skipped 30 lines
    121 124   binary.NewCataloger(),
    122 125   elixir.NewMixLockCataloger(),
    123 126   erlang.NewRebarLockCataloger(),
     127 + nix.NewStoreCataloger(),
    124 128   }, cfg.Catalogers)
    125 129  }
    126 130   
    skipped 64 lines
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/cataloger.go
     1 +package nix
     2 + 
     3 +import (
     4 + "fmt"
     5 + 
     6 + "github.com/bmatcuk/doublestar/v4"
     7 + 
     8 + "github.com/anchore/syft/internal/log"
     9 + "github.com/anchore/syft/syft/artifact"
     10 + "github.com/anchore/syft/syft/pkg"
     11 + "github.com/anchore/syft/syft/source"
     12 +)
     13 + 
     14 +const (
     15 + catalogerName = "nix-store-cataloger"
     16 + nixStoreGlob = "**/nix/store/*"
     17 +)
     18 + 
     19 +// StoreCataloger finds package outputs installed in the Nix store location (/nix/store/*).
     20 +type StoreCataloger struct{}
     21 + 
     22 +func NewStoreCataloger() *StoreCataloger {
     23 + return &StoreCataloger{}
     24 +}
     25 + 
     26 +func (c *StoreCataloger) Name() string {
     27 + return catalogerName
     28 +}
     29 + 
     30 +func (c *StoreCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
     31 + // we want to search for only directories, which isn't possible via the stereoscope API, so we need to apply the glob manually on all returned paths
     32 + var pkgs []pkg.Package
     33 + var filesByPath = make(map[string]*source.LocationSet)
     34 + for location := range resolver.AllLocations() {
     35 + matchesStorePath, err := doublestar.Match(nixStoreGlob, location.RealPath)
     36 + if err != nil {
     37 + return nil, nil, fmt.Errorf("failed to match nix store path: %w", err)
     38 + }
     39 + 
     40 + parentStorePath := findParentNixStorePath(location.RealPath)
     41 + if parentStorePath != "" {
     42 + if _, ok := filesByPath[parentStorePath]; !ok {
     43 + s := source.NewLocationSet()
     44 + filesByPath[parentStorePath] = &s
     45 + }
     46 + filesByPath[parentStorePath].Add(location)
     47 + }
     48 + 
     49 + if !matchesStorePath {
     50 + continue
     51 + }
     52 + 
     53 + storePath := parseNixStorePath(location.RealPath)
     54 + 
     55 + if storePath == nil || !storePath.isValidPackage() {
     56 + continue
     57 + }
     58 + 
     59 + p := newNixStorePackage(*storePath, location)
     60 + pkgs = append(pkgs, p)
     61 + }
     62 + 
     63 + // add file sets to packages
     64 + for i := range pkgs {
     65 + p := &pkgs[i]
     66 + locations := p.Locations.ToSlice()
     67 + if len(locations) == 0 {
     68 + log.WithFields("package", p.Name).Warn("nix package has no evidence locations associated")
     69 + continue
     70 + }
     71 + parentStorePath := locations[0].RealPath
     72 + files, ok := filesByPath[parentStorePath]
     73 + if !ok {
     74 + log.WithFields("path", parentStorePath, "nix-store-path", parentStorePath).Warn("found a nix store file for a non-existent package")
     75 + continue
     76 + }
     77 + appendFiles(p, files.ToSlice()...)
     78 + }
     79 + 
     80 + return pkgs, nil, nil
     81 +}
     82 + 
     83 +func appendFiles(p *pkg.Package, location ...source.Location) {
     84 + metadata, ok := p.Metadata.(pkg.NixStoreMetadata)
     85 + if !ok {
     86 + log.WithFields("package", p.Name).Warn("nix package metadata missing")
     87 + return
     88 + }
     89 + 
     90 + for _, l := range location {
     91 + metadata.Files = append(metadata.Files, l.RealPath)
     92 + }
     93 + 
     94 + if metadata.Files == nil {
     95 + // note: we always have an allocated collection for output
     96 + metadata.Files = []string{}
     97 + }
     98 + 
     99 + p.Metadata = metadata
     100 + p.SetID()
     101 +}
     102 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/cataloger_test.go
     1 +package nix
     2 + 
     3 +import (
     4 + "testing"
     5 + 
     6 + "github.com/anchore/syft/syft/artifact"
     7 + "github.com/anchore/syft/syft/pkg"
     8 + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
     9 + "github.com/anchore/syft/syft/source"
     10 +)
     11 + 
     12 +func TestCataloger_Catalog(t *testing.T) {
     13 + 
     14 + tests := []struct {
     15 + fixture string
     16 + wantPkgs []pkg.Package
     17 + wantRel []artifact.Relationship
     18 + }{
     19 + {
     20 + fixture: "test-fixtures/fixture-1",
     21 + wantPkgs: []pkg.Package{
     22 + {
     23 + Name: "glibc",
     24 + Version: "2.34-210",
     25 + PURL: "pkg:nix/[email protected]?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     26 + Locations: source.NewLocationSet(source.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin")),
     27 + FoundBy: catalogerName,
     28 + Type: pkg.NixPkg,
     29 + MetadataType: pkg.NixStoreMetadataType,
     30 + Metadata: pkg.NixStoreMetadata{
     31 + OutputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     32 + Output: "bin",
     33 + Files: []string{
     34 + "nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/lib",
     35 + "nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/lib/glibc.so",
     36 + "nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share",
     37 + "nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man",
     38 + "nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1",
     39 + },
     40 + },
     41 + },
     42 + },
     43 + },
     44 + }
     45 + for _, tt := range tests {
     46 + t.Run(tt.fixture, func(t *testing.T) {
     47 + c := NewStoreCataloger()
     48 + 
     49 + pkgtest.NewCatalogTester().
     50 + FromDirectory(t, tt.fixture).
     51 + Expects(tt.wantPkgs, tt.wantRel).
     52 + TestCataloger(t, c)
     53 + })
     54 + }
     55 +}
     56 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/package.go
     1 +package nix
     2 + 
     3 +import (
     4 + "github.com/anchore/packageurl-go"
     5 + "github.com/anchore/syft/syft/pkg"
     6 + "github.com/anchore/syft/syft/source"
     7 +)
     8 + 
     9 +func newNixStorePackage(storePath nixStorePath, locations ...source.Location) pkg.Package {
     10 + p := pkg.Package{
     11 + Name: storePath.name,
     12 + Version: storePath.version,
     13 + FoundBy: catalogerName,
     14 + Locations: source.NewLocationSet(locations...),
     15 + Type: pkg.NixPkg,
     16 + PURL: packageURL(storePath),
     17 + MetadataType: pkg.NixStoreMetadataType,
     18 + Metadata: pkg.NixStoreMetadata{
     19 + OutputHash: storePath.outputHash,
     20 + Output: storePath.output,
     21 + },
     22 + }
     23 + 
     24 + p.SetID()
     25 + 
     26 + return p
     27 +}
     28 + 
     29 +func packageURL(storePath nixStorePath) string {
     30 + var qualifiers packageurl.Qualifiers
     31 + if storePath.output != "" {
     32 + // since there is no nix pURL type yet, this is a guess, however, it is reasonable to assume that
     33 + // if only a single output is installed the pURL should be able to express this.
     34 + qualifiers = append(qualifiers,
     35 + packageurl.Qualifier{
     36 + Key: "output",
     37 + Value: storePath.output,
     38 + },
     39 + )
     40 + }
     41 + if storePath.outputHash != "" {
     42 + // it's not immediately clear if the hash found in the store path should be encoded in the pURL
     43 + qualifiers = append(qualifiers,
     44 + packageurl.Qualifier{
     45 + Key: "outputhash",
     46 + Value: storePath.outputHash,
     47 + },
     48 + )
     49 + }
     50 + pURL := packageurl.NewPackageURL(
     51 + // TODO: nix pURL type has not been accepted yet (only proposed at this time)
     52 + "nix",
     53 + "",
     54 + storePath.name,
     55 + storePath.version,
     56 + qualifiers,
     57 + "")
     58 + return pURL.ToString()
     59 +}
     60 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/package_test.go
     1 +package nix
     2 + 
     3 +import (
     4 + "testing"
     5 + 
     6 + "github.com/stretchr/testify/assert"
     7 +)
     8 + 
     9 +func Test_packageURL(t *testing.T) {
     10 + 
     11 + tests := []struct {
     12 + name string
     13 + storePath nixStorePath
     14 + want string
     15 + }{
     16 + {
     17 + name: "name + version",
     18 + storePath: nixStorePath{
     19 + name: "glibc",
     20 + version: "2.34",
     21 + },
     22 + want: "pkg:nix/[email protected]",
     23 + },
     24 + {
     25 + name: "hash qualifier",
     26 + storePath: nixStorePath{
     27 + name: "glibc",
     28 + version: "2.34",
     29 + outputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     30 + },
     31 + want: "pkg:nix/[email protected]?outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     32 + },
     33 + {
     34 + name: "output qualifier",
     35 + storePath: nixStorePath{
     36 + name: "glibc",
     37 + version: "2.34",
     38 + outputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     39 + output: "bin",
     40 + },
     41 + want: "pkg:nix/[email protected]?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     42 + },
     43 + }
     44 + for _, tt := range tests {
     45 + t.Run(tt.name, func(t *testing.T) {
     46 + assert.Equal(t, tt.want, packageURL(tt.storePath))
     47 + })
     48 + }
     49 +}
     50 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/parse_nix_store_path.go
     1 +package nix
     2 + 
     3 +import (
     4 + "fmt"
     5 + "path"
     6 + "regexp"
     7 + "strings"
     8 +)
     9 + 
     10 +var (
     11 + numericPattern = regexp.MustCompile(`\d`)
     12 + 
     13 + // attempts to find the right-most example of something that appears to be a version (semver or otherwise)
     14 + // example input: h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin
     15 + // example output:
     16 + // version: "2.34-210"
     17 + // major: "2"
     18 + // minor: "34"
     19 + // patch: "210"
     20 + // (there are other capture groups, but they can be ignored)
     21 + rightMostVersionIshPattern = regexp.MustCompile(`-(?P<version>(?P<major>[0-9][a-zA-Z0-9]*)(\.(?P<minor>[0-9][a-zA-Z0-9]*))?(\.(?P<patch>0|[1-9][a-zA-Z0-9]*)){0,3}(?:-(?P<prerelease>\d*[.a-zA-Z-][.0-9a-zA-Z-]*)*)?(?:\+(?P<metadata>[.0-9a-zA-Z-]+(?:\.[.0-9a-zA-Z-]+)*))?)`)
     22 + 
     23 + unstableVersion = regexp.MustCompile(`-(?P<version>unstable-\d{4}-\d{2}-\d{2})$`)
     24 +)
     25 + 
     26 +// checkout the package naming conventions here: https://nixos.org/manual/nixpkgs/stable/#sec-package-naming
     27 + 
     28 +type nixStorePath struct {
     29 + outputHash string
     30 + name string
     31 + version string
     32 + output string
     33 +}
     34 + 
     35 +func (p nixStorePath) isValidPackage() bool {
     36 + return p.name != "" && p.version != ""
     37 +}
     38 + 
     39 +func findParentNixStorePath(source string) string {
     40 + source = strings.TrimRight(source, "/")
     41 + indicator := "nix/store/"
     42 + start := strings.Index(source, indicator)
     43 + if start == -1 {
     44 + return ""
     45 + }
     46 + 
     47 + startOfHash := start + len(indicator)
     48 + nextField := strings.Index(source[startOfHash:], "/")
     49 + if nextField == -1 {
     50 + return ""
     51 + }
     52 + startOfSubPath := startOfHash + nextField
     53 + 
     54 + return source[0:startOfSubPath]
     55 +}
     56 + 
     57 +func parseNixStorePath(source string) *nixStorePath {
     58 + if strings.HasSuffix(source, ".drv") {
     59 + // ignore derivations
     60 + return nil
     61 + }
     62 + 
     63 + source = path.Base(source)
     64 + 
     65 + versionStartIdx, versionIsh, prerelease := findVersionIsh(source)
     66 + if versionStartIdx == -1 {
     67 + return nil
     68 + }
     69 + 
     70 + hashName := strings.TrimSuffix(source[0:versionStartIdx], "-")
     71 + hashNameFields := strings.Split(hashName, "-")
     72 + if len(hashNameFields) < 2 {
     73 + return nil
     74 + }
     75 + hash, name := hashNameFields[0], strings.Join(hashNameFields[1:], "-")
     76 + 
     77 + prereleaseFields := strings.Split(prerelease, "-")
     78 + lastPrereleaseField := prereleaseFields[len(prereleaseFields)-1]
     79 + 
     80 + var version = versionIsh
     81 + var output string
     82 + if !hasNumeric(lastPrereleaseField) {
     83 + // this last prerelease field is probably a nix output
     84 + version = strings.TrimSuffix(versionIsh, fmt.Sprintf("-%s", lastPrereleaseField))
     85 + output = lastPrereleaseField
     86 + }
     87 + 
     88 + return &nixStorePath{
     89 + outputHash: hash,
     90 + name: name,
     91 + version: version,
     92 + output: output,
     93 + }
     94 +}
     95 + 
     96 +func hasNumeric(s string) bool {
     97 + return numericPattern.MatchString(s)
     98 +}
     99 + 
     100 +func findVersionIsh(input string) (int, string, string) {
     101 + // we want to return the index of the start of the "version" group (the first capture group).
     102 + // note that the match indices are in the form of [start, end, start, end, ...]. Also note that the
     103 + // capture group for version in both regexes are the same index, but if the regexes are changed
     104 + // this code will start to fail.
     105 + versionGroup := 1
     106 + 
     107 + match := unstableVersion.FindAllStringSubmatchIndex(input, -1)
     108 + if len(match) > 0 && len(match[0]) > 0 {
     109 + return match[0][versionGroup*2], input[match[0][versionGroup*2]:match[0][(versionGroup*2)+1]], ""
     110 + }
     111 + 
     112 + match = rightMostVersionIshPattern.FindAllStringSubmatchIndex(input, -1)
     113 + if len(match) == 0 || len(match[0]) == 0 {
     114 + return -1, "", ""
     115 + }
     116 + 
     117 + var version string
     118 + versionStart, versionStop := match[0][versionGroup*2], match[0][(versionGroup*2)+1]
     119 + if versionStart != -1 || versionStop != -1 {
     120 + version = input[versionStart:versionStop]
     121 + }
     122 + 
     123 + prereleaseGroup := 7
     124 + 
     125 + var prerelease string
     126 + prereleaseStart, prereleaseStop := match[0][prereleaseGroup*2], match[0][(prereleaseGroup*2)+1]
     127 + if prereleaseStart != -1 && prereleaseStop != -1 {
     128 + prerelease = input[prereleaseStart:prereleaseStop]
     129 + }
     130 + 
     131 + return versionStart,
     132 + version,
     133 + prerelease
     134 +}
     135 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/parse_nix_store_path_test.go
     1 +package nix
     2 + 
     3 +import (
     4 + "path"
     5 + "testing"
     6 + 
     7 + "github.com/stretchr/testify/assert"
     8 +)
     9 + 
     10 +func Test_findVersionIsh(t *testing.T) {
     11 + // note: only the package version fields are tested here, the name is tested in parseNixStorePath below.
     12 + tests := []struct {
     13 + name string
     14 + input string
     15 + wantIdx int
     16 + wantVersion string
     17 + wantPreRelease string
     18 + }{
     19 + {
     20 + name: "no version",
     21 + input: "5q7vxm9lc4b9hifc3br4sr8dy7f2h0qa-source",
     22 + wantIdx: -1,
     23 + wantVersion: "",
     24 + wantPreRelease: "",
     25 + },
     26 + {
     27 + name: "semver with overbite into output",
     28 + input: "/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin",
     29 + wantIdx: 50,
     30 + wantVersion: "2.34-210-bin",
     31 + wantPreRelease: "210-bin",
     32 + },
     33 + {
     34 + name: "multiple versions",
     35 + input: "5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     36 + wantIdx: 53,
     37 + wantVersion: "2.33",
     38 + wantPreRelease: "",
     39 + },
     40 + {
     41 + name: "name ends with number",
     42 + input: "55nswyz8335lk954y1ccx6as2jbq1z8f-libfido2-1.10.0",
     43 + wantIdx: 42,
     44 + wantVersion: "1.10.0",
     45 + wantPreRelease: "",
     46 + },
     47 + {
     48 + name: "major-minor only",
     49 + input: "q8gnp7r8475p52k9gmdzsrcddw5hirbn-gdbm-1.23",
     50 + wantIdx: 38,
     51 + wantVersion: "1.23",
     52 + wantPreRelease: "",
     53 + },
     54 + {
     55 + name: "0-prefixed version field",
     56 + input: "r705jm2icczpnmfccby3fzfrckfjakx3-perl5.34.1-URI-5.05",
     57 + wantIdx: 48,
     58 + wantVersion: "5.05",
     59 + wantPreRelease: "",
     60 + },
     61 + {
     62 + name: "prerelease with alpha prefix",
     63 + input: "v48s6iddb518j9lc1pk3rcn3x8c2ff0j-bash-interactive-5.1-p16",
     64 + wantIdx: 50,
     65 + wantVersion: "5.1-p16",
     66 + wantPreRelease: "p16",
     67 + },
     68 + {
     69 + 
     70 + name: "0-major version",
     71 + input: "x2f9x5q6qrs6cssx09ylxqyg9q2isi1z-aws-c-http-0.6.15",
     72 + wantIdx: 44,
     73 + wantVersion: "0.6.15",
     74 + wantPreRelease: "",
     75 + },
     76 + {
     77 + 
     78 + name: "several version fields",
     79 + // note: this package version is fictitious
     80 + input: "z24qs6f5d1mmwdp73n1jfc3swj4v2c5s-krb5-1.19.3.9.10",
     81 + wantIdx: 38,
     82 + wantVersion: "1.19.3.9.10",
     83 + wantPreRelease: "",
     84 + },
     85 + {
     86 + 
     87 + name: "skip drv + major only version",
     88 + input: "z0fqylhisz47krxv8fd0izm1i2qbswfr-readline63-006.drv",
     89 + wantIdx: 44,
     90 + wantVersion: "006",
     91 + wantPreRelease: "",
     92 + },
     93 + {
     94 + 
     95 + name: "prerelease with multiple dashes",
     96 + input: "zkgyp2vra0bgqm0dv1qi514l5fd0aksx-bash-interactive-5.1-p16-man",
     97 + wantIdx: 50,
     98 + wantVersion: "5.1-p16-man",
     99 + wantPreRelease: "p16-man",
     100 + },
     101 + {
     102 + 
     103 + name: "date as major version",
     104 + input: "0amf0d1dymv9gqcyhhjb9j0l8sn00c56-libedit-20210910-3.1",
     105 + wantIdx: 41,
     106 + wantVersion: "20210910-3.1",
     107 + wantPreRelease: "3.1",
     108 + },
     109 + {
     110 + 
     111 + name: "long name",
     112 + input: "0296qxvn30z9b2ah1g5p97k5wr9k8y78-busybox-static-x86_64-unknown-linux-musl-1.35.0",
     113 + wantIdx: 74,
     114 + wantVersion: "1.35.0",
     115 + wantPreRelease: "",
     116 + },
     117 + {
     118 + // this accounts for https://nixos.org/manual/nixpkgs/stable/#sec-package-naming
     119 + // > If a package is not a release but a commit from a repository, then the version attribute must
     120 + // > be the date of that (fetched) commit. The date must be in "unstable-YYYY-MM-DD" format.
     121 + // example: https://github.com/NixOS/nixpkgs/blob/798e23beab9b5cba4d6f05e8b243e1d4535770f3/pkgs/servers/webdav-server-rs/default.nix#L14
     122 + name: "unstable version",
     123 + input: "q5dhwzcn82by5ndc7g0q83wsnn13qkqw-webdav-server-rs-unstable-2021-08-16",
     124 + wantIdx: 50,
     125 + wantVersion: "unstable-2021-08-16",
     126 + wantPreRelease: "",
     127 + },
     128 + }
     129 + for _, tt := range tests {
     130 + t.Run(tt.name, func(t *testing.T) {
     131 + gotIdx, gotVersion, gotPreRelease := findVersionIsh(tt.input)
     132 + assert.Equal(t, tt.wantIdx, gotIdx)
     133 + assert.Equal(t, tt.wantVersion, gotVersion)
     134 + assert.Equal(t, tt.wantPreRelease, gotPreRelease)
     135 + })
     136 + }
     137 +}
     138 + 
     139 +func Test_parseNixStorePath(t *testing.T) {
     140 + 
     141 + tests := []struct {
     142 + source string
     143 + want *nixStorePath
     144 + }{
     145 + {
     146 + source: "/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin",
     147 + want: &nixStorePath{
     148 + outputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     149 + name: "glibc",
     150 + version: "2.34-210",
     151 + output: "bin",
     152 + },
     153 + },
     154 + {
     155 + source: "/nix/store/0296qxvn30z9b2ah1g5p97k5wr9k8y78-busybox-static-x86_64-unknown-linux-musl-1.35.0",
     156 + want: &nixStorePath{
     157 + outputHash: "0296qxvn30z9b2ah1g5p97k5wr9k8y78",
     158 + name: "busybox-static-x86_64-unknown-linux-musl",
     159 + version: "1.35.0",
     160 + },
     161 + },
     162 + {
     163 + source: "/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     164 + want: &nixStorePath{
     165 + outputHash: "5zzrvdmlkc5rh3k5862krd3wfb3pqhyf",
     166 + name: "perl5.34.1-TimeDate",
     167 + version: "2.33",
     168 + },
     169 + },
     170 + {
     171 + source: "/nix/store/q38q8ng57zwjg1h15ry5zx0lb0xyax4b-libcap-2.63-lib",
     172 + want: &nixStorePath{
     173 + outputHash: "q38q8ng57zwjg1h15ry5zx0lb0xyax4b",
     174 + name: "libcap",
     175 + version: "2.63",
     176 + output: "lib",
     177 + },
     178 + },
     179 + {
     180 + source: "/nix/store/p0y8fbpbqr2jm5zfrdll0rgyg2lvp5g2-util-linux-minimal-2.37.4-bin",
     181 + want: &nixStorePath{
     182 + outputHash: "p0y8fbpbqr2jm5zfrdll0rgyg2lvp5g2",
     183 + name: "util-linux-minimal",
     184 + version: "2.37.4",
     185 + output: "bin",
     186 + },
     187 + },
     188 + {
     189 + source: "/nix/store/z24qs6f5d1mmwdp73n1jfc3swj4v2c5s-krb5-1.19.3.9.10",
     190 + want: &nixStorePath{
     191 + outputHash: "z24qs6f5d1mmwdp73n1jfc3swj4v2c5s",
     192 + name: "krb5",
     193 + version: "1.19.3.9.10",
     194 + },
     195 + },
     196 + {
     197 + source: "/nix/store/zkgyp2vra0bgqm0dv1qi514l5fd0aksx-bash-interactive-5.1-p16-man",
     198 + want: &nixStorePath{
     199 + outputHash: "zkgyp2vra0bgqm0dv1qi514l5fd0aksx",
     200 + name: "bash-interactive",
     201 + version: "5.1-p16",
     202 + output: "man",
     203 + },
     204 + },
     205 + {
     206 + source: "/nix/store/nwf2y0nc48ybim56308cr5ccvwkabcqc-openssl-1.1.1q",
     207 + want: &nixStorePath{
     208 + outputHash: "nwf2y0nc48ybim56308cr5ccvwkabcqc",
     209 + name: "openssl",
     210 + version: "1.1.1q",
     211 + },
     212 + },
     213 + {
     214 + source: "/nix/store/nwv742f1bxv6g78hy9yc6slxdbxlmqhb-kmod-29",
     215 + want: &nixStorePath{
     216 + outputHash: "nwv742f1bxv6g78hy9yc6slxdbxlmqhb",
     217 + name: "kmod",
     218 + version: "29",
     219 + },
     220 + },
     221 + {
     222 + source: "/nix/store/n83qx7m848kg51lcjchwbkmlgdaxfckf-tzdata-2022a",
     223 + want: &nixStorePath{
     224 + outputHash: "n83qx7m848kg51lcjchwbkmlgdaxfckf",
     225 + name: "tzdata",
     226 + version: "2022a",
     227 + },
     228 + },
     229 + {
     230 + source: "'/nix/store/q5dhwzcn82by5ndc7g0q83wsnn13qkqw-webdav-server-rs-unstable-2021-08-16",
     231 + want: &nixStorePath{
     232 + outputHash: "q5dhwzcn82by5ndc7g0q83wsnn13qkqw",
     233 + name: "webdav-server-rs",
     234 + version: "unstable-2021-08-16",
     235 + },
     236 + },
     237 + // negative cases...
     238 + {
     239 + source: "'z33yk02rsr6b4rb56lgb80bnvxx6yw39-?id=21ee35dde73aec5eba35290587d479218c6dd824.drv'",
     240 + },
     241 + {
     242 + source: "/nix/store/yzahni8aig6mdrvcsccgwm2515lcpi5q-git-minimal-2.36.0.drv",
     243 + },
     244 + {
     245 + source: "/nix/store/z9yvxs0s3xdkp5jgmzis4g50bfq3dgvm-0018-pkg-config-derive-prefix-from-prefix.patch",
     246 + },
     247 + {
     248 + source: "/nix/store/w3hl7zrmc9qvzadc0k7cp9ysxiyz88j6-base-system",
     249 + },
     250 + {
     251 + source: "/nix/store/zz1lc28x25fcx6al6xwk3dk8kp7wx47y-Test-RequiresInternet-0.05.tar.gz.drv",
     252 + },
     253 + }
     254 + for _, tt := range tests {
     255 + t.Run(path.Base(tt.source), func(t *testing.T) {
     256 + assert.Equal(t, tt.want, parseNixStorePath(tt.source))
     257 + })
     258 + }
     259 +}
     260 + 
     261 +func Test_parentNixStorePath(t *testing.T) {
     262 + 
     263 + tests := []struct {
     264 + name string
     265 + source string
     266 + want string
     267 + }{
     268 + {
     269 + name: "exact path from absolute root",
     270 + source: "/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     271 + want: "",
     272 + },
     273 + {
     274 + name: "exact path from relative root",
     275 + source: "nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     276 + want: "",
     277 + },
     278 + {
     279 + name: "clean paths",
     280 + source: "//nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33///",
     281 + want: "",
     282 + },
     283 + {
     284 + name: "relative root with subdir file",
     285 + source: "nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33/bin/perl-timedate",
     286 + want: "nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     287 + },
     288 + {
     289 + name: "absolute root with with subdir file",
     290 + source: "/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33/bin/perl-timedate",
     291 + want: "/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     292 + },
     293 + {
     294 + name: "nexted root with with subdir file",
     295 + source: "/somewhere/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33/bin/perl-timedate",
     296 + want: "/somewhere/nix/store/5zzrvdmlkc5rh3k5862krd3wfb3pqhyf-perl5.34.1-TimeDate-2.33",
     297 + },
     298 + }
     299 + for _, tt := range tests {
     300 + t.Run(tt.name, func(t *testing.T) {
     301 + assert.Equal(t, tt.want, findParentNixStorePath(tt.source))
     302 + })
     303 + }
     304 +}
     305 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/test-fixtures/fixture-1/.gitignore
     1 +# this is not a real binary, just a small text file
     2 +!nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/lib/glibc.so
  • ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/test-fixtures/fixture-1/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/lib/glibc.so
     1 +the binary
  • ■ ■ ■ ■ ■
    syft/pkg/cataloger/nix/test-fixtures/fixture-1/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1
     1 +the man pages
  • ■ ■ ■ ■ ■ ■
    syft/pkg/metadata.go
    skipped 8 lines
    9 9   
    10 10  const (
    11 11   // this is the full set of data shapes that can be represented within the pkg.Package.Metadata field
     12 + 
    12 13   UnknownMetadataType MetadataType = "UnknownMetadata"
    13 14   AlpmMetadataType MetadataType = "AlpmMetadata"
    14 15   ApkMetadataType MetadataType = "ApkMetadata"
    skipped 11 lines
    26 27   JavaMetadataType MetadataType = "JavaMetadata"
    27 28   KbPackageMetadataType MetadataType = "KbPackageMetadata"
    28 29   MixLockMetadataType MetadataType = "MixLockMetadataType"
     30 + NixStoreMetadataType MetadataType = "NixStoreMetadata"
    29 31   NpmPackageJSONMetadataType MetadataType = "NpmPackageJsonMetadata"
    30 32   NpmPackageLockJSONMetadataType MetadataType = "NpmPackageLockJsonMetadata"
    31 33   PhpComposerJSONMetadataType MetadataType = "PhpComposerJsonMetadata"
    skipped 22 lines
    54 56   JavaMetadataType,
    55 57   KbPackageMetadataType,
    56 58   MixLockMetadataType,
     59 + NixStoreMetadataType,
    57 60   NpmPackageJSONMetadataType,
    58 61   NpmPackageLockJSONMetadataType,
    59 62   PhpComposerJSONMetadataType,
    skipped 22 lines
    82 85   JavaMetadataType: reflect.TypeOf(JavaMetadata{}),
    83 86   KbPackageMetadataType: reflect.TypeOf(KbPackageMetadata{}),
    84 87   MixLockMetadataType: reflect.TypeOf(MixLockMetadata{}),
     88 + NixStoreMetadataType: reflect.TypeOf(NixStoreMetadata{}),
    85 89   NpmPackageJSONMetadataType: reflect.TypeOf(NpmPackageJSONMetadata{}),
    86 90   NpmPackageLockJSONMetadataType: reflect.TypeOf(NpmPackageLockJSONMetadata{}),
    87 91   PhpComposerJSONMetadataType: reflect.TypeOf(PhpComposerJSONMetadata{}),
    skipped 18 lines
  • ■ ■ ■ ■ ■ ■
    syft/pkg/nix_store_metadata.go
     1 +package pkg
     2 + 
     3 +import (
     4 + "sort"
     5 + 
     6 + "github.com/scylladb/go-set/strset"
     7 +)
     8 + 
     9 +type NixStoreMetadata struct {
     10 + // OutputHash is the prefix of the nix store basename path
     11 + OutputHash string `mapstructure:"outputHash" json:"outputHash"`
     12 + 
     13 + // Output allows for optionally specifying the specific nix package output this package represents (for packages that support multiple outputs).
     14 + // Note: the default output for a package is an empty string, so will not be present in the output.
     15 + Output string `mapstructure:"output" json:"output,omitempty"`
     16 + 
     17 + // Files is a listing a files that are under the nix/store path for this package
     18 + Files []string `mapstructure:"files" json:"files"`
     19 +}
     20 + 
     21 +func (m NixStoreMetadata) OwnedFiles() (result []string) {
     22 + result = strset.New(m.Files...).List()
     23 + sort.Strings(result)
     24 + return
     25 +}
     26 + 
  • ■ ■ ■ ■ ■ ■
    syft/pkg/type.go
    skipped 25 lines
    26 26   JavaPkg Type = "java-archive"
    27 27   JenkinsPluginPkg Type = "jenkins-plugin"
    28 28   KbPkg Type = "msrc-kb"
     29 + NixPkg Type = "nix"
    29 30   NpmPkg Type = "npm"
    30 31   PhpComposerPkg Type = "php-composer"
    31 32   PortagePkg Type = "portage"
    skipped 19 lines
    51 52   JavaPkg,
    52 53   JenkinsPluginPkg,
    53 54   KbPkg,
     55 + NixPkg,
    54 56   NpmPkg,
    55 57   PhpComposerPkg,
    56 58   PortagePkg,
    skipped 35 lines
    92 94   return packageurl.TypePyPi
    93 95   case PortagePkg:
    94 96   return "portage"
     97 + case NixPkg:
     98 + return "nix"
    95 99   case NpmPkg:
    96 100   return packageurl.TypeNPM
    97 101   case RpmPkg:
    skipped 53 lines
    151 155   return PortagePkg
    152 156   case packageurl.TypeHex:
    153 157   return HexPkg
     158 + case "nix":
     159 + return NixPkg
    154 160   default:
    155 161   return UnknownPkg
    156 162   }
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    syft/pkg/type_test.go
    skipped 82 lines
    83 83   purl: "pkg:hex/hpax/[email protected]",
    84 84   expected: HexPkg,
    85 85   },
     86 + {
     87 + purl: "pkg:nix/[email protected]?hash=h0cnbmfcn93xm5dg2x27ixhag1cwndga",
     88 + expected: NixPkg,
     89 + },
    86 90   }
    87 91   
    88 92   var pkgTypes []string
    skipped 28 lines
  • ■ ■ ■ ■ ■ ■
    test/cli/packages_cmd_test.go
    skipped 96 lines
    97 97   name: "squashed-scope-flag",
    98 98   args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
    99 99   assertions: []traitAssertion{
    100  - assertPackageCount(34),
     100 + assertPackageCount(35),
    101 101   assertSuccessfulReturnCode,
    102 102   },
    103 103   },
    skipped 110 lines
    214 214   // the application config in the log matches that of what we expect to have been configured.
    215 215   assertInOutput("parallelism: 2"),
    216 216   assertInOutput("parallelism=2"),
    217  - assertPackageCount(34),
     217 + assertPackageCount(35),
    218 218   assertSuccessfulReturnCode,
    219 219   },
    220 220   },
    skipped 4 lines
    225 225   // the application config in the log matches that of what we expect to have been configured.
    226 226   assertInOutput("parallelism: 1"),
    227 227   assertInOutput("parallelism=1"),
    228  - assertPackageCount(34),
     228 + assertPackageCount(35),
    229 229   assertSuccessfulReturnCode,
    230 230   },
    231 231   },
    skipped 7 lines
    239 239   assertions: []traitAssertion{
    240 240   assertNotInOutput("secret_password"),
    241 241   assertNotInOutput("secret_key_path"),
    242  - assertPackageCount(34),
     242 + assertPackageCount(35),
    243 243   assertSuccessfulReturnCode,
    244 244   },
    245 245   },
    skipped 103 lines
  • ■ ■ ■ ■ ■ ■
    test/integration/catalog_packages_cases_test.go
    skipped 389 lines
    390 390   "example-jenkins-plugin": "1.0-SNAPSHOT",
    391 391   },
    392 392   },
     393 + {
     394 + name: "find nix store packages",
     395 + pkgType: pkg.NixPkg,
     396 + pkgInfo: map[string]string{
     397 + "glibc": "2.34-210",
     398 + },
     399 + },
    393 400  }
    394 401   
  • ■ ■ ■ ■ ■
    test/integration/test-fixtures/image-pkg-coverage/pkgs/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin/share/man/glibc.1
     1 +the man pages
Please wait...
Page is in error, reload to recover