From 371cb1b9455083729cb71ac9ac0caee7aa04cde9 Mon Sep 17 00:00:00 2001 From: wilian Date: Wed, 29 Dec 2021 09:23:23 -0300 Subject: [PATCH] nancy:chore - Error not handled by Horusec in Nancy tool **- What I did** The nancy tool requires access to the Github API's, but when accessed several times without an identification it is blocked until the user identifies himself using an authentication token that can be generated via Github, so I created a validation for this scenario and the user can add this environment variable before starting an analysis. **- How to verify it** Run many times GoLang project and see follow error: ```bash Invalid character 'E' looking for beginning of value ``` **- Description for the changelog** Error not handled by Horusec in Nancy tool [#905](https://github.com/ZupIT/horusec/issues/905) Signed-off-by: wilian --- .github/workflows/security.yml | 1 + internal/helpers/messages/error.go | 7 ++ .../formatters/go/deployments/Dockerfile | 2 +- .../services/formatters/go/nancy/formatter.go | 22 ++++-- .../formatters/go/nancy/formatter_test.go | 67 +++++++++++++++++++ 5 files changed, 93 insertions(+), 6 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 328a874c8..573583085 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -30,6 +30,7 @@ jobs: fetch-depth: 0 - name: security env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HORUSEC_CLI_REPOSITORY_AUTHORIZATION: ${{ secrets.HORUSEC_CLI_REPOSITORY_AUTHORIZATION }} HORUSEC_CLI_HORUSEC_API_URI: ${{ secrets.HORUSEC_CLI_HORUSEC_API_URI }} HORUSEC_CLI_REPOSITORY_NAME: ${{ secrets.HORUSEC_CLI_REPOSITORY_NAME }} diff --git a/internal/helpers/messages/error.go b/internal/helpers/messages/error.go index e9d4e69a4..40dbac7b6 100644 --- a/internal/helpers/messages/error.go +++ b/internal/helpers/messages/error.go @@ -39,6 +39,13 @@ const ( MsgErrorGemLockNotFound = "{HORUSEC_CLI} Error It looks like your project doesn't have a gemfile.lock file, " + "it would be a good idea to commit it so horusec can check for vulnerabilities" MsgErrorGetFilenameByExt = "Could not get filename by extension: " + MsgErrorNancyRateLimit = `{HORUSEC_CLI} Nancy tool failed to query the GitHub API for updates. +This is most likely due to GitHub rate-limiting on unauthenticated requests. +To make authenticated requests please: + 1. Generate a token at https://github.com/settings/tokens + 2. Set the token by setting the GITHUB_TOKEN environment variable. +Instructions for generating a token can be found at: +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line. ` ) // Block of messages usage into log of the level error diff --git a/internal/services/formatters/go/deployments/Dockerfile b/internal/services/formatters/go/deployments/Dockerfile index f5a7c5b90..e6540357d 100644 --- a/internal/services/formatters/go/deployments/Dockerfile +++ b/internal/services/formatters/go/deployments/Dockerfile @@ -16,7 +16,7 @@ FROM golang:1.17.5-alpine RUN apk add curl -RUN curl -fsSL https://github.com/sonatype-nexus-community/nancy/releases/download/v1.0.28/nancy-v1.0.28-linux-amd64 -o /bin/nancy +RUN curl -fsSL https://github.com/sonatype-nexus-community/nancy/releases/download/v1.0.29/nancy-v1.0.29-linux-amd64 -o /bin/nancy RUN chmod +x /bin/nancy RUN wget -O - -q https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s v2.8.1 diff --git a/internal/services/formatters/go/nancy/formatter.go b/internal/services/formatters/go/nancy/formatter.go index b06c042a7..452e694e3 100644 --- a/internal/services/formatters/go/nancy/formatter.go +++ b/internal/services/formatters/go/nancy/formatter.go @@ -16,6 +16,8 @@ package nancy import ( "encoding/json" + "errors" + "os" "path/filepath" "strings" @@ -34,8 +36,10 @@ import ( ) const ( - goModulesExt = ".mod" - goSumExt = ".sum" + goModulesExt = ".mod" + goSumExt = ".sum" + rateLimitValidation = "this is most likely due to github rate-limiting on unauthenticated requests" + rateLimitPrefix = "error: failed to query the github api for updates" ) type Formatter struct { @@ -54,8 +58,13 @@ func (f *Formatter) StartAnalysis(projectSubPath string) { return } - output, err := f.startNancy(projectSubPath) - f.SetAnalysisError(err, tools.Nancy, output, projectSubPath) + if os.Getenv("GITHUB_TOKEN") == "" { + logger.LogWarnWithLevel(messages.MsgErrorNancyRateLimit) + } else { + output, err := f.startNancy(projectSubPath) + f.SetAnalysisError(err, tools.Nancy, output, projectSubPath) + } + f.LogDebugWithReplace(messages.MsgDebugToolFinishAnalysis, tools.Nancy, languages.Go) } @@ -66,10 +75,13 @@ func (f *Formatter) startNancy(projectSubPath string) (string, error) { if err != nil { return output, err } - if output == "" { return output, nil } + if strings.Contains(strings.ToLower(output), rateLimitPrefix) && + strings.Contains(strings.ToLower(output), rateLimitValidation) { + return "", errors.New(messages.MsgErrorNancyRateLimit) + } return output, f.processOutput(output, projectSubPath) } diff --git a/internal/services/formatters/go/nancy/formatter_test.go b/internal/services/formatters/go/nancy/formatter_test.go index 0c87b51c6..4846f70a4 100644 --- a/internal/services/formatters/go/nancy/formatter_test.go +++ b/internal/services/formatters/go/nancy/formatter_test.go @@ -27,6 +27,7 @@ import ( "github.com/ZupIT/horusec/config" "github.com/ZupIT/horusec/internal/entities/toolsconfig" + "github.com/ZupIT/horusec/internal/helpers/messages" "github.com/ZupIT/horusec/internal/services/formatters" "github.com/ZupIT/horusec/internal/utils/testutil" ) @@ -108,6 +109,24 @@ func TestParseOutput(t *testing.T) { assert.True(t, analysis.HasErrors(), "Expected errors on analysis") }) + t.Run("should add error on analysis when output return rate limit requests", func(t *testing.T) { + analysis := new(analysis.Analysis) + + cfg := config.New() + + dockerAPIControllerMock := testutil.NewDockerMock() + dockerAPIControllerMock.On("SetAnalysisID") + dockerAPIControllerMock.On("CreateLanguageAnalysisContainer").Return(outputRateLimit, nil) + + service := formatters.NewFormatterService(analysis, dockerAPIControllerMock, cfg) + + formatter := NewFormatter(service) + formatter.StartAnalysis("") + + assert.True(t, analysis.HasErrors(), "Expected errors on analysis") + assert.Equal(t, messages.MsgErrorNancyRateLimit, analysis.Errors) + }) + t.Run("should add error on analysis when something went wrong executing container", func(t *testing.T) { analysis := new(analysis.Analysis) @@ -221,3 +240,51 @@ const output = ` ] } ` + +const outputRateLimit = `Error: Failed to query the GitHub API for updates. + +This is most likely due to GitHub rate-limiting on unauthenticated requests. + +To make authenticated requests please: + + 1. Generate a token at https://github.com/settings/tokens + 2. Set the token by either adding it to your ~/.gitconfig or + setting the GITHUB_TOKEN environment variable. + +Instructions for generating a token can be found at: +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ + +We call the GitHub releases API to look for new releases. +More information about that API can be found here: https://developer.github.com/v3/repos/releases/ + +: Get \"https://api.github.com/repos/sonatype-nexus-community/nancy/releases\": net/http: TLS handshake timeout + +For more information, check the log file at /root/.ossindex/nancy.combined.log +nancy version: 1.0.28 + +Usage: + nancy sleuth [flags] + +Examples: + go list -json -deps | nancy sleuth --username your_user --token your_token + nancy sleuth -p Gopkg.lock --username your_user --token your_token + +Flags: + -e, --exclude-vulnerability CveListFlag Comma separated list of CVEs or OSS Index IDs to exclude (default []) + -x, --exclude-vulnerability-file string Path to a file containing newline separated CVEs or OSS Index IDs to be excluded (default \"./.nancy-ignore\") + -h, --help help for sleuth + -n, --no-color indicate output should not be colorized + -o, --output string Styling for output format. json, json-pretty, text, csv (default \"text\") + +Global Flags: + -v, -- count Set log level, multiple v's is more verbose + -d, --db-cache-path string Specify an alternate path for caching responses from OSS Inde, example: /tmp + --loud indicate output should include non-vulnerable packages + -p, --path string Specify a path to a dep Gopkg.lock file for scanning + -q, --quiet indicate output should contain only packages with vulnerabilities (default true) + --skip-update-check Skip the check for updates. + -t, --token string Specify OSS Index API token for request + -u, --username string Specify OSS Index username for request + -V, --version Get the version + +go list -m: dmitri.shuralyov.com/gpu/mtl@v0.0.0-20190408044501-666a987793e9: Get \"https://proxy.golang.org/dmitri.shuralyov.com/gpu/mtl/@v/v0.0.0-20190408044501-666a987793e9.mod\": net/http: TLS handshake timeout`