Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions src/python_inspector/resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
# See https://aboutcode.org for more information about nexB OSS projects.
#

import ast
import operator
import os
import re
import tarfile
from typing import Dict
from typing import Generator
Expand Down Expand Up @@ -281,7 +283,7 @@ def get_requirements_from_python_manifest(
"""
Return a list of parsed requirements from the ``sdist_location`` sdist location
"""
# Look in requirements file if and only if thy are refered in setup.py or setup.cfg
# Look in requirements file if and only if they are refered in setup.py or setup.cfg
# And no deps have been yielded by requirements file.
requirements = list(
get_reqs_from_requirements_file_in_sdist(
Expand All @@ -299,11 +301,48 @@ def get_requirements_from_python_manifest(
)

else:
# We should not raise exception here as we may have a setup.py that does not
# have any dependencies. We should not fail in this case.
raise Exception(
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
)
# Do not raise exception here as we may have a setup.py that does not
# have any dependencies.
with (open(setup_py_location)) as sf:
file_contents = sf.read()
node = ast.parse(file_contents)
setup_fct = [
elem
for elem in ast.walk(node)
if (
isinstance(elem, ast.Expr)
and isinstance(elem.value, ast.Call)
and isinstance(elem.value.func, ast.Name)
and elem.value.func.id == "setup"
)
]
if len(setup_fct) == 0:
raise Exception(
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
)
if len(setup_fct) > 1:
print(
f"Warning: identified multiple definitions of 'setup()' in {setup_py_location}, "
"defaulting to the first occurrence"
)
setup_fct = setup_fct[0]
install_requires = [
k.value for k in setup_fct.value.keywords if k.arg == "install_requires"
]
if len(install_requires) == 0:
raise Exception(
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
)
if len(install_requires) > 1:
print(
f"Warning: identified multiple definitions of 'install_requires' in "
"{setup_py_location}, defaulting to the first occurrence"
)
install_requires = install_requires[0].elts
if len(install_requires) != 0:
raise Exception(
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing one case which is when there are install_requires that are processed dynamically commonly either loaded from a requirements file (that we do not handle and needs "insecure loading") or from a variable (that we handle and that would be regression See https://github.com/nexB/python-inspector/blob/9e765ec50ed4c30eca20ef56686c9bcbe07fb89e/src/_packagedcode/pypi_setup_py.py#L155 )

But I ran a test with this setup.py and it works, so there is no issue:

from distutils.core import setup

reqs = ["boolean.py"]

setup(
    name="foo",
    version="0.3.0",
    install_requires=reqs,
)



DEFAULT_ENVIRONMENT = utils_pypi.Environment.from_pyver_and_os(
Expand Down
78 changes: 40 additions & 38 deletions tests/data/azure-devops.req-310-expected.json

Large diffs are not rendered by default.

78 changes: 40 additions & 38 deletions tests/data/azure-devops.req-38-expected.json

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions tests/data/pinned-pdt-requirements.txt-expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -2831,12 +2831,12 @@
"type": "pypi",
"namespace": null,
"name": "openpyxl",
"version": "3.1.0",
"version": "3.1.1",
"qualifiers": {},
"subpath": null,
"primary_language": "Python",
"description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html",
"release_date": "2023-01-31T14:40:28",
"release_date": "2023-02-13T16:51:26",
"parties": [
{
"type": "person",
Expand All @@ -2860,11 +2860,11 @@
"Programming Language :: Python :: 3.9"
],
"homepage_url": "https://openpyxl.readthedocs.io",
"download_url": "https://files.pythonhosted.org/packages/0d/89/f78a9a895e221ec8b13ae7f9495f340a0fb43563b13e2891b5df134f20ea/openpyxl-3.1.0-py2.py3-none-any.whl",
"size": 250043,
"download_url": "https://files.pythonhosted.org/packages/9e/57/1d3c2ce7f6f783be9b21569fc468a9f3660e35cc17017abfbbc26d3bd061/openpyxl-3.1.1-py2.py3-none-any.whl",
"size": 249839,
"sha1": null,
"md5": "66351b61736b19d3c88cd108908447d1",
"sha256": "24d7d361025d186ba91eff58135d50855cf035a84371b891e58fb6eb5125660f",
"md5": "864e1e1ea061fe056ade64f4e7bbaf22",
"sha256": "a0266e033e65f33ee697254b66116a5793c15fc92daf64711080000df4cfe0a8",
"sha512": null,
"bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues",
"code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl",
Expand All @@ -2884,20 +2884,20 @@
"dependencies": [],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json",
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json",
"datasource_id": null,
"purl": "pkg:pypi/[email protected].0"
"purl": "pkg:pypi/[email protected].1"
},
{
"type": "pypi",
"namespace": null,
"name": "openpyxl",
"version": "3.1.0",
"version": "3.1.1",
"qualifiers": {},
"subpath": null,
"primary_language": "Python",
"description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html",
"release_date": "2023-01-31T14:40:31",
"release_date": "2023-02-13T16:51:28",
"parties": [
{
"type": "person",
Expand All @@ -2921,11 +2921,11 @@
"Programming Language :: Python :: 3.9"
],
"homepage_url": "https://openpyxl.readthedocs.io",
"download_url": "https://files.pythonhosted.org/packages/3d/73/bb87810cdde809f69fef11d31e77297894e58710d47626dc5e5b3ff8f92a/openpyxl-3.1.0.tar.gz",
"size": 186306,
"download_url": "https://files.pythonhosted.org/packages/10/bf/950ea7896f3c42ab04073cd2903f0a190ba77ef28bdf76191f6f86373712/openpyxl-3.1.1.tar.gz",
"size": 185802,
"sha1": null,
"md5": "b7ba597b801b9a102f27599b2fa227b3",
"sha256": "eccedbe1cdd8b2494057e73959b496821141038dbb7eb9266ea59e3f34208231",
"md5": "0b1a5d776707ef471810f61c7bf77a2d",
"sha256": "f06d44e2c973781068bce5ecf860a09bcdb1c7f5ce1facd5e9aa82c92c93ae72",
"sha512": null,
"bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues",
"code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl",
Expand All @@ -2945,9 +2945,9 @@
"dependencies": [],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json",
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json",
"datasource_id": null,
"purl": "pkg:pypi/[email protected].0"
"purl": "pkg:pypi/[email protected].1"
},
{
"type": "pypi",
Expand Down Expand Up @@ -5025,7 +5025,7 @@
{
"key": "openpyxl",
"package_name": "openpyxl",
"installed_version": "3.1.0",
"installed_version": "3.1.1",
"dependencies": [
{
"key": "et-xmlfile",
Expand Down
36 changes: 18 additions & 18 deletions tests/data/pinned-requirements.txt-expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -2831,12 +2831,12 @@
"type": "pypi",
"namespace": null,
"name": "openpyxl",
"version": "3.1.0",
"version": "3.1.1",
"qualifiers": {},
"subpath": null,
"primary_language": "Python",
"description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html",
"release_date": "2023-01-31T14:40:28",
"release_date": "2023-02-13T16:51:26",
"parties": [
{
"type": "person",
Expand All @@ -2860,11 +2860,11 @@
"Programming Language :: Python :: 3.9"
],
"homepage_url": "https://openpyxl.readthedocs.io",
"download_url": "https://files.pythonhosted.org/packages/0d/89/f78a9a895e221ec8b13ae7f9495f340a0fb43563b13e2891b5df134f20ea/openpyxl-3.1.0-py2.py3-none-any.whl",
"size": 250043,
"download_url": "https://files.pythonhosted.org/packages/9e/57/1d3c2ce7f6f783be9b21569fc468a9f3660e35cc17017abfbbc26d3bd061/openpyxl-3.1.1-py2.py3-none-any.whl",
"size": 249839,
"sha1": null,
"md5": "66351b61736b19d3c88cd108908447d1",
"sha256": "24d7d361025d186ba91eff58135d50855cf035a84371b891e58fb6eb5125660f",
"md5": "864e1e1ea061fe056ade64f4e7bbaf22",
"sha256": "a0266e033e65f33ee697254b66116a5793c15fc92daf64711080000df4cfe0a8",
"sha512": null,
"bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues",
"code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl",
Expand All @@ -2884,20 +2884,20 @@
"dependencies": [],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json",
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json",
"datasource_id": null,
"purl": "pkg:pypi/[email protected].0"
"purl": "pkg:pypi/[email protected].1"
},
{
"type": "pypi",
"namespace": null,
"name": "openpyxl",
"version": "3.1.0",
"version": "3.1.1",
"qualifiers": {},
"subpath": null,
"primary_language": "Python",
"description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html",
"release_date": "2023-01-31T14:40:31",
"release_date": "2023-02-13T16:51:28",
"parties": [
{
"type": "person",
Expand All @@ -2921,11 +2921,11 @@
"Programming Language :: Python :: 3.9"
],
"homepage_url": "https://openpyxl.readthedocs.io",
"download_url": "https://files.pythonhosted.org/packages/3d/73/bb87810cdde809f69fef11d31e77297894e58710d47626dc5e5b3ff8f92a/openpyxl-3.1.0.tar.gz",
"size": 186306,
"download_url": "https://files.pythonhosted.org/packages/10/bf/950ea7896f3c42ab04073cd2903f0a190ba77ef28bdf76191f6f86373712/openpyxl-3.1.1.tar.gz",
"size": 185802,
"sha1": null,
"md5": "b7ba597b801b9a102f27599b2fa227b3",
"sha256": "eccedbe1cdd8b2494057e73959b496821141038dbb7eb9266ea59e3f34208231",
"md5": "0b1a5d776707ef471810f61c7bf77a2d",
"sha256": "f06d44e2c973781068bce5ecf860a09bcdb1c7f5ce1facd5e9aa82c92c93ae72",
"sha512": null,
"bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues",
"code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl",
Expand All @@ -2945,9 +2945,9 @@
"dependencies": [],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json",
"api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json",
"datasource_id": null,
"purl": "pkg:pypi/[email protected].0"
"purl": "pkg:pypi/[email protected].1"
},
{
"type": "pypi",
Expand Down Expand Up @@ -4976,7 +4976,7 @@
"pkg:pypi/[email protected]",
"pkg:pypi/[email protected]",
"pkg:pypi/[email protected]",
"pkg:pypi/[email protected].0",
"pkg:pypi/[email protected].1",
"pkg:pypi/[email protected]",
"pkg:pypi/[email protected]"
]
Expand Down Expand Up @@ -5066,7 +5066,7 @@
"dependencies": []
},
{
"package": "pkg:pypi/[email protected].0",
"package": "pkg:pypi/[email protected].1",
"dependencies": [
"pkg:pypi/[email protected]"
]
Expand Down
41 changes: 41 additions & 0 deletions tests/data/secure-setup/setup-emptyrequires.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Copyright 2018 Matthew Aynalem

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from distutils.core import setup

from setuptools import find_packages

setup(
name="packer.py",
version="0.3.0",
author="Matthew Aynalem",
author_email="[email protected]",
packages=["packerpy"],
url="https://github.com/mayn/packer.py",
license="Apache License 2.0",
description="packer.py - python library to run hashicorp packer CLI commands",
keywords="hashicorp packer",
long_description=open("README.rst").read(),
install_requires=[],
classifiers=[
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
],
)
40 changes: 40 additions & 0 deletions tests/data/secure-setup/setup-norequires.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
Copyright 2018 Matthew Aynalem

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from distutils.core import setup

from setuptools import find_packages

setup(
name="packer.py",
version="0.3.0",
author="Matthew Aynalem",
author_email="[email protected]",
packages=["packerpy"],
url="https://github.com/mayn/packer.py",
license="Apache License 2.0",
description="packer.py - python library to run hashicorp packer CLI commands",
keywords="hashicorp packer",
long_description=open("README.rst").read(),
classifiers=[
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
],
)
Loading