From 29615be85e8bfeaf5a0cd51829b1898c55fa4274 Mon Sep 17 00:00:00 2001 From: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Date: Thu, 30 May 2024 14:29:29 +0600 Subject: [PATCH] feat(python): add license support for `requirement.txt` files (#6782) Signed-off-by: knqyf263 Co-authored-by: knqyf263 --- docs/docs/coverage/language/python.md | 35 ++- pkg/fanal/analyzer/language/python/pip/pip.go | 198 +++++++++++++++- .../analyzer/language/python/pip/pip_test.go | 224 ++++++++++++++++-- .../requirements.txt} | 0 .../pip/testdata/{ => happy}/requirements.txt | 0 .../Flask-2.0.0.dist-info/METADATA | 124 ++++++++++ .../click-8.0.0.dist-info/METADATA | 109 +++++++++ .../Flask-2.0.0.dist-info/METADATA | 124 ++++++++++ .../click-8.0.0.dist-info/METADATA | 109 +++++++++ pkg/fanal/artifact/local/fs_test.go | 128 +++++----- 10 files changed, 948 insertions(+), 103 deletions(-) rename pkg/fanal/analyzer/language/python/pip/testdata/{not-related.txt => empty/requirements.txt} (100%) rename pkg/fanal/analyzer/language/python/pip/testdata/{ => happy}/requirements.txt (100%) create mode 100644 pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/Flask-2.0.0.dist-info/METADATA create mode 100644 pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/click-8.0.0.dist-info/METADATA create mode 100644 pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/Flask-2.0.0.dist-info/METADATA create mode 100644 pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/click-8.0.0.dist-info/METADATA diff --git a/docs/docs/coverage/language/python.md b/docs/docs/coverage/language/python.md index ce792842b978..c4f6b6d83e86 100644 --- a/docs/docs/coverage/language/python.md +++ b/docs/docs/coverage/language/python.md @@ -3,20 +3,20 @@ Trivy supports three types of Python package managers: `pip`, `Pipenv` and `Poetry`. The following scanners are supported for package managers. -| Package manager | SBOM | Vulnerability | License | -| --------------- | :---: | :-----------: | :-----: | -| pip | ✓ | ✓ | - | -| Pipenv | ✓ | ✓ | - | -| Poetry | ✓ | ✓ | - | +| Package manager | SBOM | Vulnerability | License | +|-----------------|:----:|:-------------:|:-------:| +| pip | ✓ | ✓ | ✓ | +| Pipenv | ✓ | ✓ | - | +| Poetry | ✓ | ✓ | - | In addition, Trivy supports three formats of Python packages: `egg`, `wheel` and `conda`. The following scanners are supported for Python packages. -| Packaging | SBOM | Vulnerability | License | -| --------- | :---: | :-----------: | :-----: | -| Egg | ✓ | ✓ | ✓ | -| Wheel | ✓ | ✓ | ✓ | -| Conda | ✓ | - | - | +| Packaging | SBOM | Vulnerability | License | +|-----------|:----:|:-------------:|:-------:| +| Egg | ✓ | ✓ | ✓ | +| Wheel | ✓ | ✓ | ✓ | +| Conda | ✓ | - | - | The following table provides an outline of the features Trivy offers. @@ -40,6 +40,8 @@ See [here](./index.md) for the detail. Trivy parses your files generated by package managers in filesystem/repository scanning. ### pip + +#### Dependency detection Trivy only parses [version specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#id4) with `==` comparison operator and without `.*`. To convert unsupported version specifiers - use the `pip freeze` command. @@ -91,7 +93,16 @@ urllib3==1.26.15 `requirements.txt` files don't contain information about dependencies used for development. Trivy could detect vulnerabilities on the development packages, which not affect your production environment. -License detection is not supported for `pip`. +#### License detection + +`requirements.txt` files don't contain information about licenses. +Therefore, Trivy checks `METADATA` files from `lib/site-packages` directory. + +Trivy uses 3 ways to detect `site-packages` directory: + +- Checks `VIRTUAL_ENV` environment variable. +- Detects path to `python`[^1] binary and checks `../lib/pythonX.Y/site-packages` directory. +- Detects path to `python`[^1] binary and checks `../../lib/site-packages` directory. ### Pipenv Trivy parses `Pipfile.lock`. @@ -116,4 +127,6 @@ Trivy looks for `*.egg-info`, `*.egg-info/PKG-INFO`, `*.egg` and `EGG-INFO/PKG-I ### Wheel Trivy looks for `.dist-info/META-DATA` to identify Python packages. +[^1]: Trivy checks `python`, `python3`, `python2` and `python.exe` file names. + [dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies diff --git a/pkg/fanal/analyzer/language/python/pip/pip.go b/pkg/fanal/analyzer/language/python/pip/pip.go index 380fcbf4936c..85b20a79465c 100644 --- a/pkg/fanal/analyzer/language/python/pip/pip.go +++ b/pkg/fanal/analyzer/language/python/pip/pip.go @@ -2,31 +2,92 @@ package pip import ( "context" + "fmt" + "io" + "io/fs" "os" + "os/exec" "path/filepath" + "sort" + "strings" + "github.com/samber/lo" "golang.org/x/xerrors" + goversion "github.com/aquasecurity/go-version/pkg/version" + "github.com/aquasecurity/trivy/pkg/dependency/parser/python/packaging" "github.com/aquasecurity/trivy/pkg/dependency/parser/python/pip" "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" + "github.com/aquasecurity/trivy/pkg/utils/fsutils" ) func init() { - analyzer.RegisterAnalyzer(&pipLibraryAnalyzer{}) + analyzer.RegisterPostAnalyzer(analyzer.TypePip, newPipLibraryAnalyzer) } const version = 1 -type pipLibraryAnalyzer struct{} +var pythonExecNames = []string{ + "python3", + "python", + "python2", + "python.exe", +} + +type pipLibraryAnalyzer struct { + logger *log.Logger + metadataParser packaging.Parser +} + +func newPipLibraryAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { + return pipLibraryAnalyzer{ + logger: log.WithPrefix("pip"), + metadataParser: *packaging.NewParser(), + }, nil +} + +func (a pipLibraryAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) { + var apps []types.Application -func (a pipLibraryAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { - res, err := language.Analyze(types.Pip, input.FilePath, input.Content, pip.NewParser()) + sitePackagesDir, err := a.pythonSitePackagesDir() if err != nil { - return nil, xerrors.Errorf("unable to parse requirements.txt: %w", err) + a.logger.Warn("Unable to find python `site-packages` directory. License detection is skipped.", log.Err(err)) + } + + // We only saved the `requirements.txt` files + required := func(_ string, _ fs.DirEntry) bool { + return true + } + + if err = fsutils.WalkDir(input.FS, ".", required, func(pathPath string, d fs.DirEntry, r io.Reader) error { + app, err := language.Parse(types.Pip, pathPath, r, pip.NewParser()) + if err != nil { + return xerrors.Errorf("unable to parse requirements.txt: %w", err) + } + + if app == nil { + return nil + } + + // Fill licenses + if sitePackagesDir != "" { + for i := range app.Packages { + app.Packages[i].Licenses = a.pkgLicense(app.Packages[i].Name, app.Packages[i].Version, sitePackagesDir) + } + } + + apps = append(apps, *app) + return nil + }); err != nil { + return nil, xerrors.Errorf("pip walt error: %w", err) } - return res, nil + + return &analyzer.AnalysisResult{ + Applications: apps, + }, nil } func (a pipLibraryAnalyzer) Required(filePath string, _ os.FileInfo) bool { @@ -41,3 +102,128 @@ func (a pipLibraryAnalyzer) Type() analyzer.Type { func (a pipLibraryAnalyzer) Version() int { return version } + +// pkgLicense parses `METADATA` pkg file to look for licenses +func (a pipLibraryAnalyzer) pkgLicense(pkgName, pkgVer, spDir string) []string { + // METADATA path is `**/site-packages/-.dist-info/METADATA` + pkgDir := fmt.Sprintf("%s-%s.dist-info", pkgName, pkgVer) + metadataPath := filepath.Join(spDir, pkgDir, "METADATA") + metadataFile, err := os.Open(metadataPath) + if os.IsNotExist(err) { + a.logger.Debug("No package metadata found", log.String("site-packages", pkgDir), + log.String("name", pkgName), log.String("version", pkgVer)) + return nil + } + + metadataPkg, _, err := a.metadataParser.Parse(metadataFile) + if err != nil { + a.logger.Warn("Unable to parse METADATA file", log.String("path", metadataPath), log.Err(err)) + return nil + } + + // METADATA file contains info about only 1 package + // cf. https://github.com/aquasecurity/trivy/blob/e66dbb935764908f0b2b9a55cbfe6c107f101a31/pkg/dependency/parser/python/packaging/parse.go#L86-L92 + return metadataPkg[0].Licenses +} + +// pythonSitePackagesDir returns path to site-packages dir +func (a pipLibraryAnalyzer) pythonSitePackagesDir() (string, error) { + // check VIRTUAL_ENV first + if venv := os.Getenv("VIRTUAL_ENV"); venv != "" { + libDir := filepath.Join(venv, "lib") + if _, err := os.Stat(libDir); os.IsNotExist(err) { + return "", xerrors.Errorf("unable to detect `lib` dir for %q venv: %w", venv, err) + } + + spDir, err := a.findSitePackagesDir(libDir) + if err != nil { + return "", xerrors.Errorf("unable to detect `site-packages` dir for %q venv: %w", spDir, err) + } else if spDir != "" { + return spDir, nil + } + } + + // Find path to Python executable + pythonExecPath, err := pythonExecutablePath() + if err != nil { + return "", err + } + pythonExecDir := filepath.Dir(pythonExecPath) + + // Search for a directory starting with "python" in the lib directory + libDir := filepath.Join(pythonExecDir, "..", "lib") + spDir, err := a.findSitePackagesDir(libDir) + if err != nil { + return "", xerrors.Errorf("unable to detect `site-packages` dir for %q: %w", pythonExecPath, err) + } else if spDir != "" { + return spDir, nil + } + + // Try another common pattern if the Python library directory is not found + spDir = filepath.Join(pythonExecDir, "..", "..", "lib", "site-packages") + if fsutils.DirExists(spDir) { + return spDir, nil + } + + return "", xerrors.Errorf("site-packages directory not found") +} + +// pythonExecutablePath returns path to Python executable +func pythonExecutablePath() (string, error) { + for _, execName := range pythonExecNames { + // Get the absolute path of the python command + pythonPath, err := exec.LookPath(execName) + if err != nil { + continue + } + return pythonPath, nil + } + return "", xerrors.Errorf("unable to find path to Python executable") +} + +// findSitePackagesDir finds `site-packages` dir in `lib` dir +func (a pipLibraryAnalyzer) findSitePackagesDir(libDir string) (string, error) { + entries, err := os.ReadDir(libDir) + if err != nil { + if !os.IsNotExist(err) { + return "", xerrors.Errorf("failed to read lib directory: %w", err) + } + return "", nil + } + + // Find python dir which contains `site-packages` dir + // First check for newer versions + pythonDirs := a.sortPythonDirs(entries) + for i := len(pythonDirs) - 1; i >= 0; i-- { + dir := filepath.Join(libDir, pythonDirs[i], "site-packages") + if fsutils.DirExists(dir) { + return dir, nil + } + } + return "", nil +} + +// sortPythonDirs finds dirs starting with `python` and sorts them +// e.g. python2.7 => python3.9 => python3.11 +func (a pipLibraryAnalyzer) sortPythonDirs(entries []os.DirEntry) []string { + var pythonVers []goversion.Version + for _, entry := range entries { + // Found a directory starting with "python", assume it's the Python library directory + if entry.IsDir() && strings.HasPrefix(entry.Name(), "python") { + ver := strings.TrimPrefix(entry.Name(), "python") + v, err := goversion.Parse(ver) + if err != nil { + a.logger.Debug("Unable to parse version from Python dir name", log.String("dir", entry.Name()), log.Err(err)) + continue + } + pythonVers = append(pythonVers, v) + } + } + + // Sort Python version + sort.Sort(goversion.Collection(pythonVers)) + + return lo.Map(pythonVers, func(v goversion.Version, _ int) string { + return "python" + v.String() + }) +} diff --git a/pkg/fanal/analyzer/language/python/pip/pip_test.go b/pkg/fanal/analyzer/language/python/pip/pip_test.go index 62fd13953f9b..e3041d0079c1 100644 --- a/pkg/fanal/analyzer/language/python/pip/pip_test.go +++ b/pkg/fanal/analyzer/language/python/pip/pip_test.go @@ -3,6 +3,9 @@ package pip import ( "context" "os" + "path/filepath" + "runtime" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -10,23 +13,92 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/analyzer" "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/log" ) func Test_pipAnalyzer_Analyze(t *testing.T) { + resultWithLicenses := &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.Pip, + FilePath: "requirements.txt", + Packages: types.Packages{ + { + Name: "click", + Version: "8.0.0", + Locations: []types.Location{ + { + StartLine: 1, + EndLine: 1, + }, + }, + Licenses: []string{ + "BSD License", + }, + }, + { + Name: "Flask", + Version: "2.0.0", + Locations: []types.Location{ + { + StartLine: 2, + EndLine: 2, + }, + }, + Licenses: []string{ + "BSD License", + }, + }, + { + Name: "itsdangerous", + Version: "2.0.0", + Locations: []types.Location{ + { + StartLine: 3, + EndLine: 3, + }, + }, + }, + }, + }, + }, + } + tests := []struct { - name string - inputFile string - want *analyzer.AnalysisResult - wantErr string + name string + dir string + venv string + pythonExecDir string + want *analyzer.AnalysisResult + wantErr string }{ { - name: "happy path", - inputFile: "testdata/requirements.txt", + name: "happy path with licenses from venv", + dir: filepath.Join("testdata", "happy"), + venv: filepath.Join("testdata", "libs", "python-dir"), + pythonExecDir: filepath.Join("testdata", "libs", "python-dir", "bin"), + want: resultWithLicenses, + }, + { + name: "happy path with licenses from python dir", + dir: filepath.Join("testdata", "happy"), + pythonExecDir: filepath.Join("testdata", "libs", "python-dir", "bin"), + want: resultWithLicenses, + }, + { + name: "happy path with licenses from common dir", + dir: filepath.Join("testdata", "happy"), + pythonExecDir: filepath.Join("testdata", "libs", "common-dir", "foo", "bar"), + want: resultWithLicenses, + }, + { + name: "happy path without licenses", + dir: filepath.Join("testdata", "happy"), want: &analyzer.AnalysisResult{ Applications: []types.Application{ { Type: types.Pip, - FilePath: "testdata/requirements.txt", + FilePath: "requirements.txt", Packages: types.Packages{ { Name: "click", @@ -64,29 +136,50 @@ func Test_pipAnalyzer_Analyze(t *testing.T) { }, }, { - name: "happy path with not related filename", - inputFile: "testdata/not-related.txt", - want: nil, + name: "happy path with not related filename", + dir: "testdata/empty", + want: &analyzer.AnalysisResult{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - f, err := os.Open(tt.inputFile) + if tt.venv != "" { + t.Setenv("VIRTUAL_ENV", tt.venv) + } + + var newPATH string + if tt.pythonExecDir != "" { + err := os.MkdirAll(tt.pythonExecDir, os.ModePerm) + require.NoError(t, err) + defer func() { + if strings.HasSuffix(tt.pythonExecDir, "bar") { // for `happy path with licenses from common dir` test + tt.pythonExecDir = filepath.Dir(tt.pythonExecDir) + } + err = os.RemoveAll(tt.pythonExecDir) + require.NoError(t, err) + }() + + pythonExecFileName := "python" + if runtime.GOOS == "windows" { + pythonExecFileName = "python.exe" + } + // create temp python3 Executable + err = os.WriteFile(filepath.Join(tt.pythonExecDir, pythonExecFileName), nil, 0755) + require.NoError(t, err) + + newPATH, err = filepath.Abs(tt.pythonExecDir) + require.NoError(t, err) + + } + t.Setenv("PATH", newPATH) + + a, err := newPipLibraryAnalyzer(analyzer.AnalyzerOptions{}) require.NoError(t, err) - defer f.Close() - a := pipLibraryAnalyzer{} - ctx := context.Background() - got, err := a.Analyze(ctx, analyzer.AnalysisInput{ - FilePath: tt.inputFile, - Content: f, + got, err := a.PostAnalyze(context.Background(), analyzer.PostAnalysisInput{ + FS: os.DirFS(tt.dir), }) - if tt.wantErr != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tt.wantErr) - return - } require.NoError(t, err) assert.Equal(t, tt.want, got) }) @@ -118,3 +211,90 @@ func Test_pipAnalyzer_Required(t *testing.T) { }) } } + +func Test_pythonExecutablePath(t *testing.T) { + tests := []struct { + name string + execName string + wantErr string + }{ + { + name: "happy path with `python` filename", + execName: "python", + }, + { + name: "happy path with `python3` filename", + execName: "python3", + }, + { + name: "happy path with `python2` filename", + execName: "python2", + }, + { + name: "sad path. Python executable not found", + execName: "python-wrong", + wantErr: "unable to find path to Python executable", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := t.TempDir() + binDir := filepath.Join(tmpDir, "bin") + err := os.MkdirAll(binDir, os.ModePerm) + require.NoError(t, err) + + if runtime.GOOS == "windows" { + tt.execName += ".exe" + } + err = os.WriteFile(filepath.Join(binDir, tt.execName), nil, 0755) + require.NoError(t, err) + + t.Setenv("PATH", binDir) + + path, err := pythonExecutablePath() + if tt.wantErr != "" { + require.ErrorContains(t, err, tt.wantErr) + return + } + require.NoError(t, err) + require.Equal(t, tt.execName, filepath.Base(path)) + }) + } +} + +func Test_sortPythonDirs(t *testing.T) { + dirs := []string{ + "wrong", + "wrong2.7", + "python3.11", + "python3.10", + "python2.7", + "python3.9", + "python3", + "python2", + "pythonBadVer", + } + wantDirs := []string{ + "python2", + "python2.7", + "python3", + "python3.9", + "python3.10", + "python3.11", + } + + tmp := t.TempDir() + for _, dir := range dirs { + err := os.Mkdir(filepath.Join(tmp, dir), os.ModePerm) + require.NoError(t, err) + } + + tmpDir, err := os.ReadDir(tmp) + require.NoError(t, err) + + a := pipLibraryAnalyzer{ + logger: log.WithPrefix("pip"), + } + got := a.sortPythonDirs(tmpDir) + require.Equal(t, wantDirs, got) +} diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/not-related.txt b/pkg/fanal/analyzer/language/python/pip/testdata/empty/requirements.txt similarity index 100% rename from pkg/fanal/analyzer/language/python/pip/testdata/not-related.txt rename to pkg/fanal/analyzer/language/python/pip/testdata/empty/requirements.txt diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/requirements.txt b/pkg/fanal/analyzer/language/python/pip/testdata/happy/requirements.txt similarity index 100% rename from pkg/fanal/analyzer/language/python/pip/testdata/requirements.txt rename to pkg/fanal/analyzer/language/python/pip/testdata/happy/requirements.txt diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/Flask-2.0.0.dist-info/METADATA b/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/Flask-2.0.0.dist-info/METADATA new file mode 100644 index 000000000000..5df0132dde56 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/Flask-2.0.0.dist-info/METADATA @@ -0,0 +1,124 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 2.0.0 +Summary: A simple framework for building complex web applications. +Home-page: https://palletsprojects.com/p/flask +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/flask/ +Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Requires-Dist: Werkzeug (>=2.0) +Requires-Dist: Jinja2 (>=3.0) +Requires-Dist: itsdangerous (>=2.0) +Requires-Dist: click (>=7.1.2) +Provides-Extra: async +Requires-Dist: asgiref (>=3.2) ; extra == 'async' +Provides-Extra: dotenv +Requires-Dist: python-dotenv ; extra == 'dotenv' + +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +.. _WSGI: https://wsgi.readthedocs.io/ +.. _Werkzeug: https://werkzeug.palletsprojects.com/ +.. _Jinja: https://jinja.palletsprojects.com/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) + + +Contributing +------------ + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the `contributing guidelines`_. + +.. _contributing guidelines: https://github.com/pallets/flask/blob/master/CONTRIBUTING.rst + + +Donate +------ + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Website: https://palletsprojects.com/p/flask/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/click-8.0.0.dist-info/METADATA b/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/click-8.0.0.dist-info/METADATA new file mode 100644 index 000000000000..5e67f0446795 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/pip/testdata/libs/common-dir/lib/site-packages/click-8.0.0.dist-info/METADATA @@ -0,0 +1,109 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.0.0 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Requires-Dist: colorama ; platform_system == "Windows" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Website: https://palletsprojects.com/p/click +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/Flask-2.0.0.dist-info/METADATA b/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/Flask-2.0.0.dist-info/METADATA new file mode 100644 index 000000000000..5df0132dde56 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/Flask-2.0.0.dist-info/METADATA @@ -0,0 +1,124 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 2.0.0 +Summary: A simple framework for building complex web applications. +Home-page: https://palletsprojects.com/p/flask +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/flask/ +Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Requires-Dist: Werkzeug (>=2.0) +Requires-Dist: Jinja2 (>=3.0) +Requires-Dist: itsdangerous (>=2.0) +Requires-Dist: click (>=7.1.2) +Provides-Extra: async +Requires-Dist: asgiref (>=3.2) ; extra == 'async' +Provides-Extra: dotenv +Requires-Dist: python-dotenv ; extra == 'dotenv' + +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +.. _WSGI: https://wsgi.readthedocs.io/ +.. _Werkzeug: https://werkzeug.palletsprojects.com/ +.. _Jinja: https://jinja.palletsprojects.com/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) + + +Contributing +------------ + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the `contributing guidelines`_. + +.. _contributing guidelines: https://github.com/pallets/flask/blob/master/CONTRIBUTING.rst + + +Donate +------ + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Website: https://palletsprojects.com/p/flask/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/click-8.0.0.dist-info/METADATA b/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/click-8.0.0.dist-info/METADATA new file mode 100644 index 000000000000..5e67f0446795 --- /dev/null +++ b/pkg/fanal/analyzer/language/python/pip/testdata/libs/python-dir/lib/python3.10/site-packages/click-8.0.0.dist-info/METADATA @@ -0,0 +1,109 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.0.0 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Requires-Dist: colorama ; platform_system == "Windows" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Website: https://palletsprojects.com/p/click +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/pkg/fanal/artifact/local/fs_test.go b/pkg/fanal/artifact/local/fs_test.go index 1d4029578ca9..2cee794c85b2 100644 --- a/pkg/fanal/artifact/local/fs_test.go +++ b/pkg/fanal/artifact/local/fs_test.go @@ -47,7 +47,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab", + BlobID: "sha256:e480047f53bccb8a9107a424fab43452dc59df641022a300d34326639254a0cf", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, OS: types.OS{ @@ -82,9 +82,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "host", Type: artifact.TypeFilesystem, - ID: "sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab", + ID: "sha256:e480047f53bccb8a9107a424fab43452dc59df641022a300d34326639254a0cf", BlobIDs: []string{ - "sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab", + "sha256:e480047f53bccb8a9107a424fab43452dc59df641022a300d34326639254a0cf", }, }, }, @@ -125,7 +125,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:afc2bc421aac8c61d89d4dd1c1865efb5441e3877c8a4c919232729d7c574dab", + BlobID: "sha256:e480047f53bccb8a9107a424fab43452dc59df641022a300d34326639254a0cf", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, OS: types.OS{ @@ -175,7 +175,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + BlobID: "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Applications: []types.Application{ @@ -203,9 +203,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "testdata/requirements.txt", Type: artifact.TypeFilesystem, - ID: "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + ID: "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", BlobIDs: []string{ - "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", }, }, }, @@ -216,7 +216,7 @@ func TestArtifact_Inspect(t *testing.T) { }, putBlobExpectation: cache.ArtifactCachePutBlobExpectation{ Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + BlobID: "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Applications: []types.Application{ @@ -244,9 +244,9 @@ func TestArtifact_Inspect(t *testing.T) { want: artifact.Reference{ Name: "testdata/requirements.txt", Type: artifact.TypeFilesystem, - ID: "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + ID: "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", BlobIDs: []string{ - "sha256:0c41376dbbc0dbf18e9dbd36c5de85627007dcf9357fd98f191864d48dd35537", + "sha256:c91a594202ba114ce4d067d9cac40b545c7ba2a96520c9ca8050b437020c3ab9", }, }, }, @@ -341,9 +341,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/single-failure", Type: artifact.TypeFilesystem, - ID: "sha256:1a6ce0acc3b57eb6c830c96fcd868fec1eb4d3b57ad51e481c76d85f22870a65", + ID: "sha256:5e4ca8ffaa89f49c69acfbac6d7cebb0a372b07d4c4c9876f9a58043c8ee56e9", BlobIDs: []string{ - "sha256:1a6ce0acc3b57eb6c830c96fcd868fec1eb4d3b57ad51e481c76d85f22870a65", + "sha256:5e4ca8ffaa89f49c69acfbac6d7cebb0a372b07d4c4c9876f9a58043c8ee56e9", }, }, }, @@ -426,9 +426,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/multiple-failures", Type: artifact.TypeFilesystem, - ID: "sha256:afc20cf0fc99c62bbc79b00cb9fbc70ba7ee76c946a6d560639ba9279344787d", + ID: "sha256:1832cedd0d8baeb172c7297acb56417c0dec454c280a79ee2a8f413e1ffca192", BlobIDs: []string{ - "sha256:afc20cf0fc99c62bbc79b00cb9fbc70ba7ee76c946a6d560639ba9279344787d", + "sha256:1832cedd0d8baeb172c7297acb56417c0dec454c280a79ee2a8f413e1ffca192", }, }, }, @@ -456,9 +456,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/no-results", Type: artifact.TypeFilesystem, - ID: "sha256:1827b6a0b0a17e0d623a2045e9d9c331ef613390eda2fed823969ee0dd730257", + ID: "sha256:00e01cf7bf052dbf8f02739d281675eff16f5ddf004256472cdddb55cf974fd6", BlobIDs: []string{ - "sha256:1827b6a0b0a17e0d623a2045e9d9c331ef613390eda2fed823969ee0dd730257", + "sha256:00e01cf7bf052dbf8f02739d281675eff16f5ddf004256472cdddb55cf974fd6", }, }, }, @@ -505,9 +505,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/passed", Type: artifact.TypeFilesystem, - ID: "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915", + ID: "sha256:9ee9fe14c3fcff202bc8c72f9e20a3035442ae394ec5cd201e1cb29d2111b4e1", BlobIDs: []string{ - "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915", + "sha256:9ee9fe14c3fcff202bc8c72f9e20a3035442ae394ec5cd201e1cb29d2111b4e1", }, }, }, @@ -571,9 +571,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/busted-relative-paths/child/main.tf", Type: artifact.TypeFilesystem, - ID: "sha256:8db34d644bfb98077180616caeab0b41a26d9029a47a23d4b36e1d6e45584919", + ID: "sha256:c3e6c9e68cd7a9900cd8aa690e1d5af174ddcc00ddb9438a858c3e329b9ea8f4", BlobIDs: []string{ - "sha256:8db34d644bfb98077180616caeab0b41a26d9029a47a23d4b36e1d6e45584919", + "sha256:c3e6c9e68cd7a9900cd8aa690e1d5af174ddcc00ddb9438a858c3e329b9ea8f4", }, }, }, @@ -621,9 +621,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/tfvar-outside/tf", Type: artifact.TypeFilesystem, - ID: "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915", + ID: "sha256:9ee9fe14c3fcff202bc8c72f9e20a3035442ae394ec5cd201e1cb29d2111b4e1", BlobIDs: []string{ - "sha256:eec58ef10d1b04df4af76b2472e615f8c27e253a16f90d7542670a7001d88915", + "sha256:9ee9fe14c3fcff202bc8c72f9e20a3035442ae394ec5cd201e1cb29d2111b4e1", }, }, }, @@ -711,9 +711,9 @@ func TestTerraformMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraform/relative-paths/child", Type: artifact.TypeFilesystem, - ID: "sha256:f13b89447db61be1c1e4099ef18aec7272091f8f2d3581643a9d1fabc74eda83", + ID: "sha256:44d28d3fc115f1f8dd3f8978c7e9432ba255dd82661c3810178276897e2d8fb7", BlobIDs: []string{ - "sha256:f13b89447db61be1c1e4099ef18aec7272091f8f2d3581643a9d1fabc74eda83", + "sha256:44d28d3fc115f1f8dd3f8978c7e9432ba255dd82661c3810178276897e2d8fb7", }, }, }, @@ -830,9 +830,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/single-failure", Type: artifact.TypeFilesystem, - ID: "sha256:732c38451bde877a94d1ff5b6f2019655bed04fd24b1169de195eeee1199045e", + ID: "sha256:39babdcb854331c58dc1e20c20dc67c2b4bda23895bf2861cc72d187de2bc716", BlobIDs: []string{ - "sha256:732c38451bde877a94d1ff5b6f2019655bed04fd24b1169de195eeee1199045e", + "sha256:39babdcb854331c58dc1e20c20dc67c2b4bda23895bf2861cc72d187de2bc716", }, }, }, @@ -906,9 +906,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/multiple-failures", Type: artifact.TypeFilesystem, - ID: "sha256:752c0b470adfcfe7e21892cf4c6fc3bc28dba873c9c1696f40b71b7a51ad7231", + ID: "sha256:32debc3c2857404ceeec978a938609a4b20f1c53c304603815955885377f286c", BlobIDs: []string{ - "sha256:752c0b470adfcfe7e21892cf4c6fc3bc28dba873c9c1696f40b71b7a51ad7231", + "sha256:32debc3c2857404ceeec978a938609a4b20f1c53c304603815955885377f286c", }, }, }, @@ -946,9 +946,9 @@ func TestTerraformPlanSnapshotMisconfScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/terraformplan/snapshots/passed", Type: artifact.TypeFilesystem, - ID: "sha256:8947704a08f54ab1df32cd905d6bca72edf1785a42702968bafa331172da7176", + ID: "sha256:2432b64e4583676ec1e94903d31c4faf79a1e0f4ed49bf24aef2bf9b44517ca2", BlobIDs: []string{ - "sha256:8947704a08f54ab1df32cd905d6bca72edf1785a42702968bafa331172da7176", + "sha256:2432b64e4583676ec1e94903d31c4faf79a1e0f4ed49bf24aef2bf9b44517ca2", }, }, }, @@ -1061,9 +1061,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:889a94522970c6e55f1f7543914b2f0131f79f9c4526445fb95309f64a9947d7", + ID: "sha256:43bb7ce5253686cf96a68e6d4bd30c33e163019ae2893968602da9e5e86b1aab", BlobIDs: []string{ - "sha256:889a94522970c6e55f1f7543914b2f0131f79f9c4526445fb95309f64a9947d7", + "sha256:43bb7ce5253686cf96a68e6d4bd30c33e163019ae2893968602da9e5e86b1aab", }, }, }, @@ -1145,9 +1145,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:17c9c72a759856445e6d3847b2d5ed90c3bad3e4ee50cea0c812ef53c179f8ca", + ID: "sha256:4609d64f57187099483e76a979d2f74862a092a5f42a9945e6f1242c372a811c", BlobIDs: []string{ - "sha256:17c9c72a759856445e6d3847b2d5ed90c3bad3e4ee50cea0c812ef53c179f8ca", + "sha256:4609d64f57187099483e76a979d2f74862a092a5f42a9945e6f1242c372a811c", }, }, }, @@ -1177,9 +1177,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + ID: "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", BlobIDs: []string{ - "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", }, }, }, @@ -1235,9 +1235,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/params/code/src", Type: artifact.TypeFilesystem, - ID: "sha256:267b572211115db6a2a4484a02317fbb6d4f050da0e95b1db4243d49889483de", + ID: "sha256:abaeb2f443a59940afd63e015d0bb737127ebde06306840f529dd40d65390703", BlobIDs: []string{ - "sha256:267b572211115db6a2a4484a02317fbb6d4f050da0e95b1db4243d49889483de", + "sha256:abaeb2f443a59940afd63e015d0bb737127ebde06306840f529dd40d65390703", }, }, }, @@ -1293,9 +1293,9 @@ func TestCloudFormationMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/cloudformation/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:8ca92725ce2f47b7ffb1b0a9e0359d59ac2b3b3f517ba42f66a859436057e54a", + ID: "sha256:73bb13d7c722bfcdf6c00f51f368befda453e1acba31ba62aad31b5b04b235e8", BlobIDs: []string{ - "sha256:8ca92725ce2f47b7ffb1b0a9e0359d59ac2b3b3f517ba42f66a859436057e54a", + "sha256:73bb13d7c722bfcdf6c00f51f368befda453e1acba31ba62aad31b5b04b235e8", }, }, }, @@ -1381,9 +1381,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9", + ID: "sha256:059f081288e7ea418286bddcee78167e8ebf33b47e365c20754b6cfa180d997d", BlobIDs: []string{ - "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9", + "sha256:059f081288e7ea418286bddcee78167e8ebf33b47e365c20754b6cfa180d997d", }, }, }, @@ -1439,9 +1439,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9", + ID: "sha256:059f081288e7ea418286bddcee78167e8ebf33b47e365c20754b6cfa180d997d", BlobIDs: []string{ - "sha256:627cbf451ec7929dfe5151dfe0e2305ed855906bf79136f198528a0cc3f6e4f9", + "sha256:059f081288e7ea418286bddcee78167e8ebf33b47e365c20754b6cfa180d997d", }, }, }, @@ -1469,9 +1469,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + ID: "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", BlobIDs: []string{ - "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", }, }, }, @@ -1529,9 +1529,9 @@ func TestDockerfileMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/dockerfile/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:4cc7f6bba417cc65c5391bc9c07fd1e205e21bdec87b271889433af18be1e454", + ID: "sha256:5f6504b01b68ef1418d59210c0c7b3604fe63f8575a72721d1172d9d2fdd2e23", BlobIDs: []string{ - "sha256:4cc7f6bba417cc65c5391bc9c07fd1e205e21bdec87b271889433af18be1e454", + "sha256:5f6504b01b68ef1418d59210c0c7b3604fe63f8575a72721d1172d9d2fdd2e23", }, }, }, @@ -1621,9 +1621,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:d5ca0b4e96aaaeafa424a2250db6297a5182cb6ca5db49bc1ff11790f6cdbee9", + ID: "sha256:14768f3c82388c43e0af6579632535b5ecd6bd4ac802d063d74b636725191fe9", BlobIDs: []string{ - "sha256:d5ca0b4e96aaaeafa424a2250db6297a5182cb6ca5db49bc1ff11790f6cdbee9", + "sha256:14768f3c82388c43e0af6579632535b5ecd6bd4ac802d063d74b636725191fe9", }, }, }, @@ -1707,9 +1707,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:eef9fff2fe8f5c4a123c018b4f91db25d9676e7d171a3a683c2fbfbbbe82fa54", + ID: "sha256:d7b5fe7fb0e8d51cb6a06b5f2027b1e976e25a2462ff40241f86e13e69ff210c", BlobIDs: []string{ - "sha256:eef9fff2fe8f5c4a123c018b4f91db25d9676e7d171a3a683c2fbfbbbe82fa54", + "sha256:d7b5fe7fb0e8d51cb6a06b5f2027b1e976e25a2462ff40241f86e13e69ff210c", }, }, }, @@ -1737,9 +1737,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:2b54cf33feaa1fe1f5bf223f873ca6c3f7c3693b0bb3b0ce9e2e7fd79cd37b5a", + ID: "sha256:ddd0e363b0ebab71250f9d36de65d485ca2faa9510ab6ddea940de7af8267b67", BlobIDs: []string{ - "sha256:2b54cf33feaa1fe1f5bf223f873ca6c3f7c3693b0bb3b0ce9e2e7fd79cd37b5a", + "sha256:ddd0e363b0ebab71250f9d36de65d485ca2faa9510ab6ddea940de7af8267b67", }, }, }, @@ -1797,9 +1797,9 @@ func TestKubernetesMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/kubernetes/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:dc7a0fd3ea2f13b0ea05f4e517a16e602b0fc17fbd72aa5e34107ef12a91a30b", + ID: "sha256:af77d733739a4366b6e03e95605f5282262d45905efed501d83ec7ecc97a7574", BlobIDs: []string{ - "sha256:dc7a0fd3ea2f13b0ea05f4e517a16e602b0fc17fbd72aa5e34107ef12a91a30b", + "sha256:af77d733739a4366b6e03e95605f5282262d45905efed501d83ec7ecc97a7574", }, }, }, @@ -1886,9 +1886,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/single-failure/src", Type: artifact.TypeFilesystem, - ID: "sha256:c1a8bfd544b9041ad194382cc42b54289f70966d061ef501b267aec8fd07c5df", + ID: "sha256:ff25ae7d346f724faf4d2653868bc249bf221460bcf6d364cf50372c303342d2", BlobIDs: []string{ - "sha256:c1a8bfd544b9041ad194382cc42b54289f70966d061ef501b267aec8fd07c5df", + "sha256:ff25ae7d346f724faf4d2653868bc249bf221460bcf6d364cf50372c303342d2", }, }, }, @@ -1968,9 +1968,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/multiple-failures/src", Type: artifact.TypeFilesystem, - ID: "sha256:75bf0e88f8d2857be90fb8d10a350c04c1532ba7f510e1eb404a8bae30ce97d8", + ID: "sha256:e5c5ad752c6ff8d26f1b6764a9fb6dec345157df7c816b86d491b0af9e9f4ae6", BlobIDs: []string{ - "sha256:75bf0e88f8d2857be90fb8d10a350c04c1532ba7f510e1eb404a8bae30ce97d8", + "sha256:e5c5ad752c6ff8d26f1b6764a9fb6dec345157df7c816b86d491b0af9e9f4ae6", }, }, }, @@ -1998,9 +1998,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/no-results/src", Type: artifact.TypeFilesystem, - ID: "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + ID: "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", BlobIDs: []string{ - "sha256:26c76a2cb55cb0ef2c3a2dd79e237bddb508ca2c4cefdb103698a1972c8a9c2d", + "sha256:a3d40c3290bf45542f9c0aa364f2c16aca06cdccb4868a2e442b7e6a56c6157a", }, }, }, @@ -2054,9 +2054,9 @@ func TestAzureARMMisconfigurationScan(t *testing.T) { want: artifact.Reference{ Name: "testdata/misconfig/azurearm/passed/src", Type: artifact.TypeFilesystem, - ID: "sha256:b9ba7c4eafec405c8b6998dbb98ee1c7f7830caf8487fd1461433ff82d8779e9", + ID: "sha256:0702eea6f699984f98c788c737f3adf74ae00db2b24b7d44577c7eedc31b1eb1", BlobIDs: []string{ - "sha256:b9ba7c4eafec405c8b6998dbb98ee1c7f7830caf8487fd1461433ff82d8779e9", + "sha256:0702eea6f699984f98c788c737f3adf74ae00db2b24b7d44577c7eedc31b1eb1", }, }, },