Code Monkey home page Code Monkey logo

salus's Introduction

Salus

Salus: Guardian of Code Safety and Security

CircleCI

๐Ÿ” Overview

Salus (Security Automation as a Lightweight Universal Scanner), named after the Roman goddess of protection, is a tool for coordinating the execution of security scanners. You can run Salus on a repository via the Docker daemon and it will determine which scanners are relevant, run them and provide the output. Most scanners are other mature open source projects which we include directly in the container.

Salus is particularly useful for CI/CD pipelines because it becomes a centralized place to coordinate scanning across a large fleet of repositories. Typically, scanners are configured at the repository level for each project. This means that when making org wide changes to how the scanners are run, each repository must be updated. Instead, you can update Salus and all builds will instantly inherit the change.

Salus supports powerful configuration that allows for global defaults and local tweaks. Finally, Salus can report metrics on each repository, such as what packages are included or what concerns exist. These reports can be centrally evaluated in your infrastructure to allow for scalable security tracking.

Using Salus

# Navigate to the root directory of the project you want to run Salus on
cd /path/to/repo

# Run the following line while in the root directory (No edits necessary)
docker run --rm -t -v $(pwd):/home/repo coinbase/salus

Supported Scanners

  • Bandit - Execution of Bandit 1.6.2, looks for common security issues in Python code.
  • Brakeman - Execution of Brakeman 5.3.1, looks for vulnerable code in Rails projects.
  • semgrep - Execution of semgrep 1.0.0, which looks for semantic and syntactical patterns in code at the AST level.
  • BundleAudit - Execution of bundle-audit 0.8.0, looks for CVEs in ruby gem dependencies.
  • Gosec - Execution of gosec 2.11.0, looks for security problems in go code.
  • npm audit - Execution of npm audit 6.14.8 which looks for CVEs in node module dependencies.
  • yarn audit - Execution of yarn audit 1.22.0 which looks for CVEs in node module dependencies.
  • PatternSearch - Execution of sift 0.9.0, looks for certain strings in a project that might be dangerous or could require that certain strings be present.
  • TruffleHog - Execution of TruffleHog 3.19.0, looks for leaked credentials.
  • Cargo Audit - Execution of Cargo Audit 0.14.0 Audit Cargo.lock files for crates with security vulnerabilities reported to the RustSec Advisory Database

Dependency Tracking

Salus also parses dependency files and reports which libraries and versions are being used. This can be useful for tracking dependencies across your fleet.

Currently supported languages are:

  • Ruby
  • Node.js (Javascript)
  • Python
  • Go
  • Rust

Configuration

Salus is designed to be highly configurable so that it can work in many different types of environments and with many different scanners. It supports environment variable interpolation and cascading configurations, and can read configuration and post reports over HTTP.

Sometimes it's necessary to ignore certain CVEs, rules, tests, groups, directories, or otherwise modify the default configuration for a scanner. The docs/scanners directory explains how to do so for each scanner that Salus supports.

If you would like to build custom scanners or support more languages that are not currently supported, you can use this method of building custom Salus images.

CircleCI Integration

Salus can be integrated with CircleCI by using a public Orb. All Salus configuration options are supported, and defaults are the same as for Salus itself.

Example CircleCI config.yml:

version: 2.1

orbs:
  salus: federacy/[email protected]

workflows:
  main:
    jobs:
      - salus/scan

Orb documentation

Github Actions Integration

Salus can also be used with Github Actions.

Example .github/workflows/main.yml:

on: [push]

jobs:
  salus_scan_job:
    runs-on: ubuntu-latest
    name: Salus Security Scan Example
    steps:
    - uses: actions/checkout@v1
    - name: Salus Scan
      id: salus_scan
      uses: federacy/[email protected]

Github Action documentation

Using Salus in your Repo

For your given CI, update the config file to run salus. In circle, it will look like this:

docker run --rm -t -v $(pwd):/home/repo coinbase/salus

coinbase/salus pulls the docker image

๐Ÿ‘ทโ€โ™‚๏ธ Development

Contribution to this project is extremely welcome and it's our sincere hope that the work we've done to this point only serves as a foundation for allowing the security/development communities as a whole to come together to improve the security of everyone's infrastructure.

You can read more about getting your development environment set up, or the architecture of Salus.

You can also find steps to add a new scanner to Salus

๐Ÿ“ƒ License

This project is available open source under the terms of the Apache 2.0 License.

salus's People

Contributors

0xalec avatar 0xdiba avatar as3richa avatar aunyks avatar cbsisl avatar cbtoni avatar coinsnaulty avatar dependabot[bot] avatar drewdennison avatar dustmason avatar geraldnash-cb avatar ghbren avatar h0bbbbes avatar hesh64 avatar jborrey avatar jeffrey778zhan avatar joshuaostrom avatar joshuaostrom-cb avatar jsulinski avatar kamsiy avatar kiwiz avatar maitrayshah-cb avatar mrcoinbase avatar nishils avatar raphdev avatar saikat056 avatar salmcb avatar saron-deb avatar swkanwar avatar xolaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

dashbaord202401

salus's Issues

Semgrep patterns failing on 2.10.1

Salus appears to call semgrep with the --strict flag as of 2.10.1. This has resulted in our Semgrep patterns failing with a parse error (semgrep exit code 3). What's odd if that these patterns work as expected when semgrep is called directly. It's also worth noting that we use Salus via the federacy/scan-action GitHub Action.

Manual run with one pattern:

$ semgrep --version
0.10.1
$ semgrep --strict --json --pattern "req.body" --lang javascript --exclude-dir node_modules --exclude-dir bower_components --exclude-dir express .
{"results": [], "errors": []}
$ echo $?
0

Relevant section from salus-config.yml:

scanner_configs:
  Semgrep:
    matches:
      - pattern: eval(...)
        message: Eval is Evil
        language: javascript
        forbidden: true
        exclude_directory:
          - node_modules
          - bower_components
      - pattern: req.body
        message: Use req.validated.body
        language: javascript
        forbidden: true
        exclude_directory:
          - node_modules
          - bower_components
          - express
      - pattern: req.params
        message: Use req.validated.url
        language: javascript
        forbidden: true
        exclude_directory:
          - node_modules
          - bower_components
          - express
      - pattern: req.query
        message: Use req.validated.query
        language: javascript
        forbidden: true
        exclude_directory:
          - node_modules
          - bower_components
          - express

Salus error:

~~ Errors:

 [
   {
     "status": 3,
     "stderr": "parse error ",
     "message": "Call to semgrep failed"
   },
   {
     "status": 3,
     "stderr": "parse error ",
     "message": "Call to semgrep failed"
   },
   {
     "status": 3,
     "stderr": "parse error ",
     "message": "Call to semgrep failed"
   },
   {
     "status": 3,
     "stderr": "parse error ",
     "message": "Call to semgrep failed"
   }
 ]

Bundler 2 Errors

This is for anybody else that runs into this issue.

bundler: failed to load command: ./bin/salus (./bin/salus)
Bundler::LockfileError: You must use Bundler 2 or greater with this lockfile.

Currently, Salus does not support Gemfiles produced by Bundler 2.x.x. The workaround is to re-bundle your application with Bundler 1.x.x. You can see which bundler you are running with bundler -v or by checking the Gemfile.lock file to see which bundler version produced the Gemfile.lock

Add Support for Sobelow (Elixir)

We've been using Salus for awhile now at my current company and have integrated Sobelow into it for the purposes of scanning Elixir code.

Our implementation is not ready for primetime via a PR and we're unsure if we have time to dedicate to cleaning up our fork so it's ready for a PR; so we'd love some assistance getting it integrated from official maintainers so we don't have to continue supporting our fork as it drifts further and further away from the main branch.

Update dependency CVE databases before each run

Run bundle audit check --update to update ruby cve db without having to rebuild container.

We should look into being able to do this for npm and yarn so the db isn't tied to when the docker container is built.

Unreviewed commit on master!

Unreviewed commit(s) COMPARE was merged to master by joshuaostrom-cb.

Comment with appropriate number of ๐Ÿ‘ to approve.


Reviewed requirements satisfied? No
Ancestors reviewed? No

Github Action Integration

With Github Actions now available to everyone, it would be great to support running Salus as an action, similar to the CircleCI integration.

Salus Help Command Line Doc Bug

:O I didnt' know the = was needed. Thanks for the help :) I can confirm it works! Also I didn't know that the file was relative to /home, usually it's relative to where we are calling the command, or you can send the full path to ensure it's correct.

Regarding the parameter, I was trying what is specified here: https://github.com/coinbase/salus/blob/master/docs/configuration.md

--config file://tests/salus-config.yaml

From within it says:

root@16f932d54825:/home# bundle exec ./bin/salus help
Commands:
  salus help [COMMAND]  # Describe available commands or one specific command
  salus scan            # Scan the source code of a repository.

Options:
  -c, [--config=CONFIG]                # Point to local or remote configuration files. e.g. --config="file path/to/salus.yaml"
  -q, [--quiet], [--no-quiet]          # Do not print reports to STDOUT.
  -v, [--verbose], [--no-verbose]      # Include "info" level data in reports printed to STDOUT.
  -d, [--repo-path=REPO_PATH]          # Path to a directory to scan.
                                       # Default: ./repo
      [--no-colors], [--no-no-colors]  # Do not colorize output.

Maybe it could say specifically # Point to local or remote configuration files. e.g. --config="file://path/to/salus.yaml" (with file:// instead of space).

Either way, thank you very much @nishils !!

Originally posted by @GMartinez-Sisti in #72 (comment)

Yarn Audit Scan takes a lot of resources

When scanning a few different repos like https://github.com/coinbase/rest-hooks, yarn audit --json will produce 19 GB which then get entirely placed into memory and is handled inefficiently. This particularly affects CI scans that may expect some sort of response from salus within a time period. Currently, Salus only outputs on completion.

There's a couple of options to fix this issue.

  1. Wait for upstream fix yarnpkg/yarn#7404
  2. (Stop gap) Implement a heartbeat to prevent CI from timing out
  3. (Longer term if no upstream fix) Implement a streaming parser that de-dupes without having to load the entire file into memory.

Regex used for project name validation having unexpected effect

This is the function which checks for validity of project name https://github.com/coinbase/salus/blob/5effc53b5037d5e33ae3a9e91e5faf26cfe642e3/lib/salus/config.rb#L114-L118

Going by the error message it produces, it is supposed to check for whitespaces and semicolon. But it also filters out Square brackets characters because of the way regex are written in Ruby.
https://github.com/coinbase/salus/blob/5effc53b5037d5e33ae3a9e91e5faf26cfe642e3/lib/salus/config.rb#L95-L98

Example code showing valid_name? will filter out any project names with square brackets in them, https://ideone.com/MV7c4O

Add pnpm audit support

It would be great if salus supported pnpm support in addition to npm and yarn. The output of pnpm audit --json is identical to NPM, so hopefully this is a simple request :)

One caveat to be aware of is that pnpm places the lockfile at the the root of the repository in a monorepo/workspaces setup. For example:

package-a/
  package.json
package-b/
  package.json
package.json
pnpm-lock.yaml

If package-a had its own salus-config.yaml, and we were running the scanner with --repo_path=/some/path/to/package-a, the should_run check would need to recursively look upwards for the folder containing .git and see if pnpm-lock.yaml exists at the same level.

GitHub Action example configuration fails because `cargo-audit` not found

I set up a basic GitHub Action attempting to run the Salus scanner, via this PR: underdog-tech/vulnbot#13

The action file is copied/pasted directly from the examples, with the exception of the actions/checkout version and what triggers cause it to run.

This action is failing with the following:

reports:
  - uri: file://salus-report.json
    format: json
    verbose: true
Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_checker)' instead.
[INFORMATIONAL: 2023-03-28 15:52:15 +0000]: Salus is running.
#<Thread:0x00007f67b9e18d18 /home/lib/salus/processor.rb:105 run> terminated with exception (report_on_exception is true):
/usr/local/lib/ruby/3.2.0/open3.rb:222:in `spawn': No such file or directory - cargo-audit (Errno::ENOENT)
	from /usr/local/lib/ruby/3.2.0/open3.rb:222:in `popen_run'
	from /usr/local/lib/ruby/3.2.0/open3.rb:103:in `popen3'
	from /usr/local/lib/ruby/3.2.0/open3.rb:290:in `capture3'
	from /home/lib/salus/scanners/base.rb:149:in `run_shell'
	from /home/lib/salus/scanners/cargo_audit.rb:65:in `version'
	from /home/lib/salus/scanners/base.rb:[34](https://github.com/underdog-tech/dependabot-alert-bot/actions/runs/4544749565/jobs/8011940142#step:4:35):in `initialize'
	from /home/lib/salus/processor.rb:106:in `new'
	from /home/lib/salus/processor.rb:106:in `block (2 levels) in run_scanner'
bundler: failed to load command: /home/bin/salus (/home/bin/salus)
/usr/local/lib/ruby/3.2.0/open3.rb:222:in `spawn': No such file or directory - cargo-audit (Errno::ENOENT)
	from /usr/local/lib/ruby/3.2.0/open3.rb:222:in `popen_run'
	from /usr/local/lib/ruby/3.2.0/open3.rb:103:in `popen3'
	from /usr/local/lib/ruby/3.2.0/open3.rb:290:in `capture3'
	from /home/lib/salus/scanners/base.rb:149:in `run_shell'
	from /home/lib/salus/scanners/cargo_audit.rb:65:in `version'
	from /home/lib/salus/scanners/base.rb:34:in `initialize'
	from /home/lib/salus/processor.rb:106:in `new'
	from /home/lib/salus/processor.rb:106:in `block (2 levels) in run_scanner'

It appears that this is expecting the cargo-audit command to always be present on the system, which is not the case for a default ubuntu-latest image, and certainly not the case for a Go-based project.

Integrate against Clair for Docker image scanning

This will take some work as Clair would need to be external to Salus. We would add support for pushing images to Clair and getting the results.

We can provide a way to configure against an existing Clair instance but would not want to make Clair a part of Salus.

I have used paclair before and seemed to work rather well for this sort of use case.

YarnAudit fails for large yarn.lock files

Hi,

We started receiving the following error when executing Salus YarnAudit scan agains our repository:

==== YarnAudit: FAILED in 120.72s

 ~~ Errors:

  [
    {
      "message": "Unhandled exception running YarnAudit: JSON::ParserError: 751: unexpected token at
   ''",
      "error_class": "JSON::ParserError",
      "backtrace": [
        "/usr/local/lib/ruby/2.4.0/json/common.rb:156:in `parse'",
        "/usr/local/lib/ruby/2.4.0/json/common.rb:156:in `parse'",
        "/home/lib/salus/scanners/yarn_audit.rb:48:in `block in scan_for_cves'",
        "/home/lib/salus/scanners/yarn_audit.rb:47:in `map'",
        "/home/lib/salus/scanners/yarn_audit.rb:47:in `scan_for_cves'"
      ]
    }
  ]

After a lot of troubleshooting, I believe the issue is caused by our yarn.lock file that has 12k+ lines and the size of the stdout buffer.

I parsed the yarn.lock file, with this script to understand the output of the file.

Here are our tests:

yarn.lock lines Parsed json file size Salus YarnAudit result
~12k 903K Fails with above error
~9k 474K Fails with above error
~8k 422K Scan succeeds

I hope this information helps.

Please let me know if you need more information, or if you want me to test a specific branch.

Regards

Update NPMAudit version

Hi there, currently I'm trying to update the node version of a project to verion 15.14.0 + npm 7.7.6, but the NPMAudit still runs on version 6.14.8. ==== NPMAudit v6.14.8: FAILED in 2.13s

I'm using the latest image coinbase/salus:latest

Is there a way to force an update?

Complete requirements parsing/processing for Python

Per {this}, it seems like the current story for python package information is reading the requirements.txt file. Often times, we find that when developers don't practice proper dependency management, this file is not really the source of truth for all packages that are pulled into the build artifact. With that being said, is there something on the roadmap to parse the contents of the virtualenv and the collection of system level installed python packages?

SARIF support

A number of scanners that Salus comes with include SARIF support. I'm hoping to send these results to Github's Code Scanning dashboard, so that we have a consistent way of reviewing code quality issues.

I don't think there's currently a way to expose this yet - is there interest in a PR & any suggestions on how to expose this option?

--config parameter doesn't work

The config parameter is not being parsed correctly. I've read all the documentation multiple times and even check the code, but I can't found the problem.

This is an example where I rename the default config and then try to load the new file, I've also tried appending without removing, but the new files are never loaded and there is no complain:

โ†’ docker run --rm -it --entrypoint=bash -v $(pwd):/home/repo coinbase/salus:2.6.1
root@cc58caacc33b:/home# mv salus-default.yaml salus-default-new.yaml
root@cc58caacc33b:/home# bundle exec /home/bin/salus scan --config "file://salus-default-new.yaml"
bundler: failed to load command: /home/bin/salus (/home/bin/salus)
Errno::ENOENT: No such file or directory @ rb_sysopen - /home/lib/salus/../../salus-default.yaml
  /home/vendor/bundle/ruby/2.4.0/gems/safe_yaml-1.0.5/lib/safe_yaml/load.rb:157:in `initialize'
  /home/vendor/bundle/ruby/2.4.0/gems/safe_yaml-1.0.5/lib/safe_yaml/load.rb:157:in `open'
  /home/vendor/bundle/ruby/2.4.0/gems/safe_yaml-1.0.5/lib/safe_yaml/load.rb:157:in `load_file'
  /home/vendor/bundle/ruby/2.4.0/gems/safe_yaml-1.0.5/lib/safe_yaml.rb:33:in `safe_load_file'
  /home/vendor/bundle/ruby/2.4.0/gems/safe_yaml-1.0.5/lib/safe_yaml.rb:22:in `load_file_with_options'
  /home/lib/salus/config.rb:29:in `<class:Config>'
  /home/lib/salus/config.rb:5:in `<module:Salus>'
  /home/lib/salus/config.rb:4:in `<top (required)>'
  /home/lib/salus.rb:18:in `require'
  /home/lib/salus.rb:18:in `<top (required)>'
  /home/bin/salus:6:in `require'
  /home/bin/salus:6:in `<top (required)>'
root@cc58caacc33b:/home# ls salus-default-new.yaml
salus-default-new.yaml

Am I doing something wrong, or is this a bug?

Thanks

Salus Orb

From #10, @raphdev brought up the following:

A small improvement we've made is simplifying for CircleCI through an orb. This allows teams to integrate Salus and any configuration, simply by including the orb. The orb would have the correct docker image/version, and remote configuration locations managed by the security team. One benefit of this is that we no longer require updating several pipelines for updates that aren't in the container itself, such as handling of reporting, since these are reused from the orb.
Does something like this sound like a valuable contribution?

Thanks for bringing this to my attention! I need to keep up with the CircleCI blog more.

Yeah I certainly think that a Salus orb could be useful. Not sure if the Coinbase team wants to own the creation of that or @raphdev, are you considering making your orb general purpose to work outside of your org?

Error with Default Configs in Orb federacy/[email protected]

Description
Running into issue with default usage of Salus CircleCI Orb.

Versions

  • CircleCI Orb:federacy/[email protected]
  • Docker: coinbase/salus@sha256:8ed3483526f17aa90745b322839465803b86064501d08dda1589ada303c471bb

Error Message
Could not send Salus report: (StandardError: Local report uri /home/repo/../salus-report.json should be relative to repo path and cannot have invalid chars)

Expected results

  • Run Example setup and receive uploaded artifact

Actual Results

  • Received Error Message referenced above ^^

Related Info

It looks like the current default path is not meant to work, based on this commit and test condition

Workarounds

I tweaked this section of the orb.yml job and had the storage_artifact consume the remote_uri filename parameter

ClairScanner Question

Hi! I don't know if it is appropriate to ask such questions. I have a question about is it possible to change the option "Required" for ClairScanner? I didn't find any information about this issue in the docs.

Interest in adding ruby_audit to the list of scanners?

hey! ๐Ÿ‘‹ this is a neat idea and a pretty cool project.

I was looking thru the ruby stuff and saw that you had bundler-audit in there, which rules. I thought I'd suggest adding a similar library that checks for ruby language vulnerabilities, which get flagged reasonably frequently. The library in question is over here: https://github.com/civisanalytics/ruby_audit we've been using it at @DCAFEngineering for awhile and it's worked pretty well for us.

I'm more than happy to take a crack at this if this sounds useful, figured I would check first. Let me know!

Let us know if you're using Salus

As we develop Salus, it's useful to know how it's being used. If you would like, please comment below about where you use it, how and for what purpose.

Golang 1.13 support

I have an application that uses os.UserConfigDir(), which was introduced in golang 1.13. This is causing Salus to fail and report a Golang error: "UserConfigDir not declared by package os". You can see an example build here. I'm using the federacy GitHub action to trigger salus.

I see in the release notes for Salus 2.7.1 that golang 1.12.10 is currently used. Is there any way to force salus to use golang 1.13, disable building the golang code (I perform this action in another CI job), or some other solution? This is the last thing holding me back from merging the Salus CI job!

Purpose of `safe_local_report_path`?

Relevant XKCD:

Hi there, I'm curious about what the path.include?("/.") check in safe_local_report_path is for. The reason I ask is because I'm currently populating the output into a JSON file located at REPO_PATH/.salus/salus.json, which triggers this condition.

Could the pattern be updated to "/..", which is less likely to be valid (I can submit a PR if so)?

Adding a new scanner checklist

Provide a checklist of what every scanner should support in terms of integrating with Salus.

This can include things like

  • please write tests
  • please add documentation in the salus docs folder
  • please document config in the salus docs folder.

This will make sure that scanners are consistent and make it easier for folks to contribute.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.