Package: skjold
.         .    .      Skjold /skjɔl/
    ,-. | , . ,-. |  ,-|
    `-. |<  | | | |  | |      Security audit python project dependencies
    `-' ' ` | `-' `' `-´      against several security advisory databases.
           `'IntroductionIt currently supports fetching advisories from the following sources:SourceNameNotesGitHub Advisory DatabasegithubRequires Access Token (SeeGithub).PyUP.io safety-dbpyupGitLab gemnasium-dbgemnasiumPYPA Advisory DatabasepypaOnly supportsECOSYSTEM!OSV.dev DatabaseosvOnly supportsECOSYSTEM!Sends package information toOSV.devAPI.No source is enabled by default! Sources can be enabled by settingsourceslist (seeConfiguration). There is (currently) no de-duplication meaning that using too many sources at once will result ina lotof duplicates.skjoldalso requiresalldependencies to be passed as itwill notresolve any dependencies at runtime!MotivationSkjold was initially created for myself to replacesafety.Which appears to no longer receive monthly updates (seepyupio/safety-db #2282). I wanted something I can run locally and use for my local or private projects/scripts.I currently also use it during CI builds and before deploying/publishing containers or packages.Installationskjoldcan be installed from eitherPyPIor directly fromGithubusingpip:pipinstallskjold# Install from PyPIpipinstallgit+https://github.com/twu/skjold.git@vX.X.X# Install from GithubThis should provide a script namedskjoldthat can then be invoked. SeeUsage.Usage$piplist--format=freeze|skjold-vaudit--sourcesgemnasium-When runningauditone can either provide a path to afrozenrequirements.txt, apoetry.lockor aPipfile.lockfile. Alternatively, dependencies can also be passed in viastdin(formatted aspackage==version).skjoldwill maintain a local cache (undercache_dir) that will expire automatically aftercache_expireshas passed. Thecache_dirandcache_expirescan be adjusted by setting them intools.skjoldsection of the projectspyproject.toml(seeConfigurationfor more details). Thecache_dirwill be created automatically, and by default unless otherwise specified will be located under$HOME/.skjold/cache.For further options please readskjold --helpand/orskjold audit --help.ExamplesAll examples involvinggithubassume thatSKJOLD_GITHUB_API_TOKENis already set (seeGithub).# Using pip list. Checking against GitHub only.$piplist--format=freeze|skjoldaudit-sgithub-# Be verbose. Read directly from supported formats.$skjold-vauditrequirements.txt
$skjold-vauditpoetry.lock
$skjold-vauditPipenv.lock# Specify specify multiple inputs at once.$skjold-vauditPipenv.lockpoetry.lockrequirements.txt# Using poetry.$poetryexport-frequirements.txt|skjoldaudit-sgithub-sgemnasium-spyup-# Using poetry, format output as json and pass it on to jq for additional filtering.$poetryexport-frequirements.txt|skjoldaudit-ojson-sgithub-|jq'.[0]'# Using Pipenv, checking against Github$pipenvrunpiplist--format=freeze|skjoldaudit-sgithub-# Checking a single package via stdin against Github and format findings as json.$echo"urllib3==1.23"|skjoldaudit-ojson-r-sgithub-[{"severity":"HIGH","name":"urllib3","version":"1.23","versions":"<1.24.2","source":"github","summary":"High severity vulnerability that affects urllib3","references":["https://nvd.nist.gov/vuln/detail/CVE-2019-11324"],"url":"https://github.com/advisories/GHSA-mh33-7rrq-662w"}]# Checking a single package via stdin against Gemnasium and report findings (`-o cli`).$echo"urllib3==1.23"|skjoldaudit-ocli-r-sgemnasium-urllib3==1.23(<=1.24.2)viagemnasium

CRLFinjection.Intheurllib3libraryforPython,CRLFinjectionispossibleiftheattackercontrolstherequestparameter.
https://nvd.nist.gov/vuln/detail/CVE-2019-11236
--urllib3==1.23(<1.24.2)viagemnasium

WeakAuthenticationCausedByImproperCertificateValidation.Theurllib3
libraryforPythonmishandlescertaincaseswherethedesiredsetofCA
certificatesisdifferentfromtheOSstoreofCAcertificates,whichresultsinSSLconnectionssucceedinginsituationswhereaverificationfailureisthe
correctoutcome.Thisisrelatedtouseofthe`ssl_context`,`ca_certs`,or`ca_certs_dir`argument.
https://nvd.nist.gov/vuln/detail/CVE-2019-11324
--urllib3==1.23(<1.25.9)viagemnasium

InjectionVulnerability.urllib3allowsCRLFinjectioniftheattackercontrols
theHTTPrequestmethod,asdemonstratedbyinserting`CR`and`LF`control
charactersinthefirstargumentof`putrequest()`.NOTE:thisissimilarto
CVE-2020-26116.
https://nvd.nist.gov/vuln/detail/CVE-2020-26137
--Ignore FindingsFindings can be ignored either by manually adding an entry using the sources identifier to a file named.skjoldignore(SeeExample) or by using in the CLI. Below are a few possible usage examples.# Ignore PYSEC-2020-148 finding from PyPA source until a certain date with a specific reason.
$ skjold ignore urllib3 PYSEC-2020-148 --reason "Very good reason." --expires "2021-01-01T00:00:00+00:00"
Ignore urllib3 in PYSEC-2020-148 until 2021-01-01 00:00:00+00:00?
Very good reason.
--
Add to '.skjoldignore'? [y/N]: y

# Ignore PYSEC-2020-148 finding from PyPA source for 7 days with "No immediate remediation." reason.
$ skjold ignore urllib3 PYSEC-2020-148
Ignore urllib3 in PYSEC-2020-148 until ...?
No immediate remediation.
--
Add to '.skjoldignore'? [y/N]: y

# Audit `poetry.lock` using a custom `.skjoldignore` file location via `ENV`...
$ SKJOLD_IGNORE_FILE=<path-to-file> skjold audit -s pyup poetry.lock

# ... or using -i/--ignore-file
$ skjold audit -s pyup -i <path-to-file> poetry.lockConfigurationskjoldcan read its configuration from thetools.skjoldsection of a projectspyproject.toml. Arguments specified via the command-line should take precedence over any configured or default value.[tool.skjold]sources=["github","pyup","gemnasium"]# Sources to check against.report_only=false# Exit with non-zero exit code on findings.report_format='json'# Output findings as `json`. Default is 'cli'.cache_dir='.skjold_cache'# Cache location (default: `~/.skjold/cache`).cache_expires=86400# Cache max. age.ignore_file='.skjoldignore'# Ignorefile location (default `.skjoldignore`).verbose=true# Be verbose.To take a look at the current configuration / defaults run:$skjoldconfig
sources:['pyup','github','gemnasium']report_only:False
report_format:json
verbose:False
cache_dir:.skjold_cache
cache_expires:86400ignore_file='.skjoldignore'GithubFor thegithubsource to work you'll need to provide a Github API Token via anENVvariable namedSKJOLD_GITHUB_API_TOKEN. You cancreate a new Github Access Token here. Youdo nothave to give itanypermissions as it is only required to query theGitHub GraphQL API v4API.Version Control IntegrationTo useskjoldwith the excellentpre-commitframework add the following to the projects.pre-commit-config.yamlafterinstallation.repos:-repo:https://github.com/twu/skjoldrev:vX.X.Xhooks:-id:skjoldverbose:true# Important if used with `report_only`, see below.After runningpre-commit installthe hook should be good to go. To configureskjoldin this scenario I recommend adding the entire configuration to the projectspyproject.tomlinstead of manipulating the hookargs. See this projectspyproject.tomlfor an example.Important!: When usingskjoldas apre-commit-hook it only gets triggered if you want to commit changed dependency files (e.g.Pipenv.lock,poetry.lock,requirements.txt,...).
It will not continuously check your dependencies oneverycommit!You could runpre-commit run skjold --all-filesmanually in your workflow/scripts or runskjoldmanually.
If you have a better solution please let me know!Important!: If you usereport_onlyin any way make sure that you addverbose: trueto your hook configuration
otherwisepre-commitwon't show you any output since the hook is always returning with a zero exit code due
toreport_onlybeing set!ContributingPull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.Please make sure to update tests as appropriate.