From 8cde561fb9a21344e729d32d6f632d46d87ff966 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Fri, 10 Feb 2023 05:48:29 -0500 Subject: [PATCH] fix: ensure pyproject.toml has lock (#5409) --- .../analyzer/PoetryAnalyzer.java | 39 ++++++++++++---- .../analyzer/PoetryAnalyzerTest.java | 7 +++ .../python-myproject-toml/pyproject.toml | 46 +++++++++++++++++++ 3 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 core/src/test/resources/python-myproject-toml/pyproject.toml diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java index b95c66cdee1..238598de3d5 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java @@ -35,10 +35,9 @@ import org.owasp.dependencycheck.utils.Settings; import com.moandjiezana.toml.Toml; -import org.apache.commons.lang3.StringUtils; +import java.io.File; import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem; import org.owasp.dependencycheck.dependency.naming.GenericIdentifier; -import org.owasp.dependencycheck.dependency.naming.Identifier; import org.owasp.dependencycheck.dependency.naming.PurlIdentifier; import org.owasp.dependencycheck.utils.Checksum; import org.slf4j.Logger; @@ -69,12 +68,15 @@ public class PoetryAnalyzer extends AbstractFileTypeAnalyzer { * Lock file name. */ private static final String POETRY_LOCK = "poetry.lock"; - + /** + * Poetry project file. + */ + private static final String PYPROJECT_TOML = "pyproject.toml"; /** * The file filter for poetry.lock */ private static final FileFilter POETRY_LOCK_FILTER = FileFilterBuilder.newInstance() - .addFilenames(POETRY_LOCK) + .addFilenames(POETRY_LOCK, PYPROJECT_TOML) .build(); /** @@ -145,6 +147,13 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An //do not report on the build file itself engine.removeDependency(dependency); + if (PYPROJECT_TOML.equals(dependency.getActualFile().getName())) { + final File parentPath = dependency.getActualFile().getParentFile(); + ensureLock(parentPath); + //exit as we can't analyze pyproject.toml - insufficient version information + return; + } + final Toml result = new Toml().read(dependency.getActualFile()); final List projectsLocks = result.getTables("package"); if (projectsLocks == null) { @@ -161,12 +170,12 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An d.setVersion(version); try { - final PackageURL purl = PackageURLBuilder.aPackageURL() - .withType("pypi") - .withName(name) - .withVersion(version) - .build(); - d.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST)); + final PackageURL purl = PackageURLBuilder.aPackageURL() + .withType("pypi") + .withName(name) + .withVersion(version) + .build(); + d.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST)); } catch (MalformedPackageURLException ex) { LOGGER.debug("Unable to build package url for pypi", ex); d.addSoftwareIdentifier(new GenericIdentifier("pypi:" + name + "@" + version, Confidence.HIGH)); @@ -185,4 +194,14 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An engine.addDependency(d); }); } + + private void ensureLock(File parent) throws AnalysisException { + final File lock = new File(parent, POETRY_LOCK); + final File requirements = new File(parent, "requirements.txt"); + final boolean found = lock.isFile() || requirements.isFile(); + if (!found) { + throw new AnalysisException("Python `pyproject.toml` found and there " + + "is not a `poetry.lock` or `requirements.txt` - analysis will be incomplete"); + } + } } diff --git a/core/src/test/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzerTest.java b/core/src/test/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzerTest.java index 75360edb4d6..643d9fd79b3 100644 --- a/core/src/test/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzerTest.java +++ b/core/src/test/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzerTest.java @@ -72,4 +72,11 @@ public void testPoetryLock() throws AnalysisException { } assertTrue("Expeced to find PyYAML", found); } + + @Test(expected = AnalysisException.class) + public void testPyprojectToml() throws AnalysisException { + final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, "python-myproject-toml/pyproject.toml")); + //causes an exception. + analyzer.analyze(result, engine); + } } diff --git a/core/src/test/resources/python-myproject-toml/pyproject.toml b/core/src/test/resources/python-myproject-toml/pyproject.toml new file mode 100644 index 00000000000..231c160577c --- /dev/null +++ b/core/src/test/resources/python-myproject-toml/pyproject.toml @@ -0,0 +1,46 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "s3-metadata-tagger" +version = "1.0.1" +description = "A package to add metadata tags to objects saved in s3" +readme = "README.md" +requires-python = ">=3.7" +keywords = ["aws", "s3", "metadata"] +license = { file="LICENSE" } +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: POSIX :: Linux", + "Topic :: Multimedia", +] +dependencies = [ + "autopep8", + "boto3", + "boto3-stubs", + "botocore", + "botocore-stubs", + "mypy-boto3-s3", + "pycodestyle", + "typing_extensions", +] + +[project.optional-dependencies] +pdf = ["PyPDF2"] +picture = ["Pillow", "types-Pillow"] + +[project.urls] +"Homepage" = "https://github.com/DDS-GmbH/s3-metadata-tagger-lib/" +"Bug Tracker" = "https://github.com/DDS-GmbH/s3-metadata-tagger-lib/issues" + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.package-data] +metadata_tagger = ["py.typed"] \ No newline at end of file