github.com/google/osv-scalibr@v0.4.1/docs/new_detector.md (about) 1 # Adding a new SCALIBR Detector 2 3 Detectors are plugins that SCALIBR uses to detect security findings such as 4 vulnerabilities on the scanned artifact. They all implement the `Detector` 5 interface and have read access to all files on the filesystem through it. 6 7 <!-- See detector/detector.go symbol \bDetector\b --> 8 9 <!-- See plugin/plugin.go symbol \bPlugin\b --> 10 11 ## Steps for writing a new detector 12 13 See the [/etc/shadow weak credentials detector](/detector/weakcredentials/etcshadow/etcshadow.go) 14 as an example. 15 16 1. Set up your detector package in an [appropriate location](#code-location). 17 1. Add a `New()` function that returns your detector struct from the specified 18 plugin config. 19 1. If you'd like to add new plugin-specific config settings for your Detector, 20 1. Add them as a new message to [config.proto](third_party/scalibr/binary/proto/config.proto). 21 1. Re-generate the go_proto: 22 23 ``` 24 $ `make protos` 25 ``` 26 1. Implement the [`Detector`](/detector/detector.go) 27 interface with your struct: 28 * Implement `Name()` to return a unique name, e.g. `cve/nginxldapauth`. 29 * Implement `Version()` to return 0. Increase it in the future whenever 30 larger changes are made to the detector. 31 * Implement `DetectedFinding()` to return [generic info](#output-format) 32 about what is detected. 33 * Implement `Scan()` (see [param list](#scan-parameters)) to run your 34 detection logic and [return](#output-format) the security findings. 35 1. Write tests. 36 1. Register your detector in 37 [list.go](/detector/list/list.go) 38 so you can use it in the CLI. 39 1. Update `docs/supported_inventory_types.md` to include your new detector. 40 1. If you added new dependencies, regenerate the go.mod file by running 41 42 ```sh 43 $ `go mod tidy` 44 ``` 45 46 1. Test your new detector on a local machine, using the plugin `Name()` to 47 enable it, e.g. 48 49 ``` 50 scalibr --detectors=cve/nginxldapauth ... 51 ``` 52 53 See the 54 [README](/README.md#as-a-standalone-binary) 55 for more details on how to run SCALIBR locally. 56 57 1. Submit your code for review. 58 59 Once your code is merged, you can add your detector to the list of available 60 detectors in 61 [detector/list/list.go](/detector/list/list.go). 62 Please submit this code separately from the main detector logic. 63 64 ## Code location 65 66 All new detectors should be in a sub-folder of 67 [detector/](/detector/). 68 If there's already a directory that fits the detector's category (e.g. cis) 69 place it in there. Otherwise, feel free to create a new directory. Feel free 70 to ask SCALIBR devs for location suggestions during code review. 71 72 ## Scan parameters 73 74 Detectors can access the filesystem and the results of the package extraction 75 step through the parameters of their `Scan()` function. 76 77 ### Filesystem access 78 79 Detectors receive a [`fs.FS`](https://pkg.go.dev/io/fs#FS) implementation which 80 allows them to read the contents and permissions of any file on the scanned 81 filesystem. Note that the access is read-only: Detectors are not able to make 82 changes to the target machine. 83 84 ### Package index 85 86 Detectors also receive a 87 [`PackageIndex`](/packageindex/package_index.go) 88 param that can be used to query the software package that the extraction step 89 found on the filesystem. This can be used to run the detection logic on each relevant 90 software found, or exit early if none are installed. For an example use case see the 91 [govulncheck Detector](/detector/govulncheck/binary/binary.go). 92 93 ## Output format 94 95 Detectors return their vulnerability findings in the 96 [`Finding`](/inventory/finding.go) 97 struct. Package related vulnerabilities use the `PackageVuln` struct while more 98 generic findings use `GenericFinding`. Feel free to add a new struct if you're 99 planning to introduce a new category of vulnerabilities to scan for. 100 See the comments in the `Finding` struct and 101 [existing Detector implementations](/detector/govulncheck/binary/binary.go) 102 for guidance on how to fill these structs out. 103 104 One thing to keep in mind: `GenericFindings` are uniquely identified by the 105 `GenericFindingAdvisory` field, including the `AdvisoryID`. A detector should 106 always return the same `GenericFindingAdvisory` with its own unique 107 `AdvisoryID`. If you want to set target-specific information 108 (e.g. which users had weak passwords), you can add it 109 to `GenericFindingTargetDetails`. 110 111 `PackageVulns` are uniquely identified by the contents of their `Vulnerability` 112 field. A detector should thus always return the same `Vulnerability`, with the 113 exception of the `DatabaseSpecific` field. If you want to set target-specific 114 information (e.g. the exact version of the vulnerable package found), you can 115 add it to the `DatabaseSpecific` field of `Vulnerability`. 116 117 Since `DetectedFinding()` returns generic info about the vulnerability, you'll 118 generally want to return a `GenericFinding` struct with only the 119 `GenericFindingAdvisory` or a `PackageVuln` struct with only the `Vulnerability` 120 (and no `DatabaseSpecific`) field set. 121 122 Make sure you appropriately fill the "Description" and "Recommendation" fields 123 of these structs. 124 125 In case you have any questions or feedback, feel free to open an issue.