diff --git a/tests/common/db/integrations.py b/tests/common/db/integrations.py new file mode 100644 index 000000000000..64744d383056 --- /dev/null +++ b/tests/common/db/integrations.py @@ -0,0 +1,31 @@ +# 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. + +import factory + +from warehouse.integrations.vulnerabilities.models import VulnerabilityRecord + +from .base import WarehouseFactory +from .packaging import ReleaseFactory + + +class VulnerabilityRecordFactory(WarehouseFactory): + class Meta: + model = VulnerabilityRecord + + id = factory.fuzzy.FuzzyText(length=12) + source = factory.fuzzy.FuzzyText(length=12) + link = factory.fuzzy.FuzzyText(length=12) + aliases = factory.Sequence(lambda n: "alias" + str(n)) + releases = factory.SubFactory(ReleaseFactory) + details = factory.fuzzy.FuzzyText(length=12) + fixed_in = factory.Sequence(lambda n: str(n) + ".0") diff --git a/tests/unit/integration/vulnerabilities/test_package.py b/tests/unit/integration/vulnerabilities/test_package.py index 75d637bf072b..56521c2dbc0e 100644 --- a/tests/unit/integration/vulnerabilities/test_package.py +++ b/tests/unit/integration/vulnerabilities/test_package.py @@ -46,6 +46,8 @@ def test_vulnerability_report_request_from_api_request(): "id": "vuln_id", "link": "vulns.com/vuln_id", "aliases": ["vuln_alias"], + "details": "some details", + "events": [{"introduced": "1.0.0"}, {"fixed": "1.0.1"}, {"fixed": "2.0.0"}], } ) @@ -54,6 +56,8 @@ def test_vulnerability_report_request_from_api_request(): assert request.vulnerability_id == "vuln_id" assert request.advisory_link == "vulns.com/vuln_id" assert request.aliases == ["vuln_alias"] + assert request.details == "some details" + assert request.fixed_in == ["1.0.1", "2.0.0"] def test_invalid_vulnerability_report(): diff --git a/tests/unit/legacy/api/test_json.py b/tests/unit/legacy/api/test_json.py index a1066c1b1af1..6d6d70b86b46 100644 --- a/tests/unit/legacy/api/test_json.py +++ b/tests/unit/legacy/api/test_json.py @@ -20,6 +20,7 @@ from warehouse.packaging.models import Dependency, DependencyKind from ....common.db.accounts import UserFactory +from ....common.db.integrations import VulnerabilityRecordFactory from ....common.db.packaging import ( DescriptionFactory, FileFactory, @@ -432,6 +433,7 @@ def test_detail_renders(self, pyramid_config, db_request, db_session): } ], "last_serial": je.id, + "vulnerabilities": [], } def test_minimal_renders(self, pyramid_config, db_request): @@ -538,8 +540,38 @@ def test_minimal_renders(self, pyramid_config, db_request): } ], "last_serial": je.id, + "vulnerabilities": [], } + def test_vulnerabilities_renders(self, pyramid_config, db_request): + project = ProjectFactory.create(has_docs=False) + release = ReleaseFactory.create(project=project, version="0.1") + VulnerabilityRecordFactory.create( + id="PYSEC-001", + source="the source", + link="the link", + aliases=["alias1", "alias2"], + details="some details", + fixed_in=["3.3.2"], + releases=[release], + ) + + url = "/the/fake/url/" + db_request.route_url = pretend.call_recorder(lambda *args, **kw: url) + + result = json.json_release(release, db_request) + + assert result["vulnerabilities"] == [ + { + "id": "PYSEC-001", + "source": "the source", + "link": "the link", + "aliases": ["alias1", "alias2"], + "details": "some details", + "fixed_in": ["3.3.2"], + }, + ] + class TestJSONReleaseSlash: def test_normalizing_redirects(self, db_request): diff --git a/warehouse/integrations/vulnerabilities/__init__.py b/warehouse/integrations/vulnerabilities/__init__.py index ae8b2a672ae4..88a6ea72e8ea 100644 --- a/warehouse/integrations/vulnerabilities/__init__.py +++ b/warehouse/integrations/vulnerabilities/__init__.py @@ -30,12 +30,16 @@ def __init__( vulnerability_id: str, advisory_link: str, aliases: List[str], + details: str, + fixed_in: List[str], ): self.project = project self.versions = versions self.vulnerability_id = vulnerability_id self.advisory_link = advisory_link self.aliases = aliases + self.details = details + self.fixed_in = fixed_in @classmethod def from_api_request(cls, request): @@ -59,6 +63,13 @@ def from_api_request(cls, request): vulnerability_id=request["id"], advisory_link=request["link"], aliases=request["aliases"], + details=request.get("details"), + fixed_in=[ + version + for event in request.get("events", []) + for event_type, version in event.items() + if event_type == "fixed" + ], ) diff --git a/warehouse/integrations/vulnerabilities/models.py b/warehouse/integrations/vulnerabilities/models.py index 509cc9b84105..88bb0a99a8c6 100644 --- a/warehouse/integrations/vulnerabilities/models.py +++ b/warehouse/integrations/vulnerabilities/models.py @@ -58,6 +58,12 @@ class VulnerabilityRecord(db.Model): # e.g. "CVE-2021-12345" aliases = Column(ARRAY(String)) + # Details about the vulnerability + details = Column(String) + + # Events of introduced/fixed versions + fixed_in = Column(ARRAY(String)) + releases = orm.relationship( "Release", back_populates="vulnerabilities", diff --git a/warehouse/integrations/vulnerabilities/utils.py b/warehouse/integrations/vulnerabilities/utils.py index ea920ffb676a..851ebebfa2ea 100644 --- a/warehouse/integrations/vulnerabilities/utils.py +++ b/warehouse/integrations/vulnerabilities/utils.py @@ -89,6 +89,8 @@ def _analyze_vulnerability(request, vulnerability_report, origin, metrics): source=origin, link=report.advisory_link, aliases=report.aliases, + details=report.details, + fixed_in=report.fixed_in, ) _add_vuln_record(request, vulnerability_record) diff --git a/warehouse/legacy/api/json.py b/warehouse/legacy/api/json.py index 83b3532050e0..50b3da030c9f 100644 --- a/warehouse/legacy/api/json.py +++ b/warehouse/legacy/api/json.py @@ -163,6 +163,19 @@ def json_release(release, request): for r, fs in releases.items() } + # Serialize a list of vulnerabilties for this release + vulnerabilities = [ + { + "id": vulnerability_record.id, + "source": vulnerability_record.source, + "link": vulnerability_record.link, + "aliases": vulnerability_record.aliases, + "details": vulnerability_record.details, + "fixed_in": vulnerability_record.fixed_in, + } + for vulnerability_record in release.vulnerabilities + ] + return { "info": { "name": project.name, @@ -198,6 +211,7 @@ def json_release(release, request): }, "urls": releases[release.version], "releases": releases, + "vulnerabilities": vulnerabilities, "last_serial": project.last_serial, } diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index e1d3bd86f396..f68c74723545 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -315,65 +315,67 @@ msgstr "" #: warehouse/templates/packaging/detail.html:318 #: warehouse/templates/pages/classifiers.html:25 #: warehouse/templates/pages/help.html:20 -#: warehouse/templates/pages/help.html:204 -#: warehouse/templates/pages/help.html:211 -#: warehouse/templates/pages/help.html:225 -#: warehouse/templates/pages/help.html:241 -#: warehouse/templates/pages/help.html:245 -#: warehouse/templates/pages/help.html:302 -#: warehouse/templates/pages/help.html:329 -#: warehouse/templates/pages/help.html:334 -#: warehouse/templates/pages/help.html:339 -#: warehouse/templates/pages/help.html:341 -#: warehouse/templates/pages/help.html:346 -#: warehouse/templates/pages/help.html:347 -#: warehouse/templates/pages/help.html:348 -#: warehouse/templates/pages/help.html:352 -#: warehouse/templates/pages/help.html:385 -#: warehouse/templates/pages/help.html:387 +#: warehouse/templates/pages/help.html:207 +#: warehouse/templates/pages/help.html:214 +#: warehouse/templates/pages/help.html:228 +#: warehouse/templates/pages/help.html:244 +#: warehouse/templates/pages/help.html:248 +#: warehouse/templates/pages/help.html:305 +#: warehouse/templates/pages/help.html:332 +#: warehouse/templates/pages/help.html:337 +#: warehouse/templates/pages/help.html:342 +#: warehouse/templates/pages/help.html:344 +#: warehouse/templates/pages/help.html:349 +#: warehouse/templates/pages/help.html:350 +#: warehouse/templates/pages/help.html:351 +#: warehouse/templates/pages/help.html:355 +#: warehouse/templates/pages/help.html:388 #: warehouse/templates/pages/help.html:390 -#: warehouse/templates/pages/help.html:426 -#: warehouse/templates/pages/help.html:431 -#: warehouse/templates/pages/help.html:437 -#: warehouse/templates/pages/help.html:495 -#: warehouse/templates/pages/help.html:515 -#: warehouse/templates/pages/help.html:521 +#: warehouse/templates/pages/help.html:393 +#: warehouse/templates/pages/help.html:429 +#: warehouse/templates/pages/help.html:434 +#: warehouse/templates/pages/help.html:440 +#: warehouse/templates/pages/help.html:498 +#: warehouse/templates/pages/help.html:518 #: warehouse/templates/pages/help.html:524 -#: warehouse/templates/pages/help.html:526 -#: warehouse/templates/pages/help.html:535 -#: warehouse/templates/pages/help.html:547 -#: warehouse/templates/pages/help.html:553 -#: warehouse/templates/pages/help.html:565 -#: warehouse/templates/pages/help.html:566 -#: warehouse/templates/pages/help.html:571 -#: warehouse/templates/pages/help.html:596 -#: warehouse/templates/pages/help.html:627 -#: warehouse/templates/pages/help.html:650 -#: warehouse/templates/pages/help.html:657 -#: warehouse/templates/pages/help.html:669 -#: warehouse/templates/pages/help.html:680 +#: warehouse/templates/pages/help.html:527 +#: warehouse/templates/pages/help.html:529 +#: warehouse/templates/pages/help.html:538 +#: warehouse/templates/pages/help.html:550 +#: warehouse/templates/pages/help.html:556 +#: warehouse/templates/pages/help.html:568 +#: warehouse/templates/pages/help.html:569 +#: warehouse/templates/pages/help.html:574 +#: warehouse/templates/pages/help.html:599 +#: warehouse/templates/pages/help.html:612 +#: warehouse/templates/pages/help.html:617 +#: warehouse/templates/pages/help.html:643 +#: warehouse/templates/pages/help.html:666 +#: warehouse/templates/pages/help.html:673 #: warehouse/templates/pages/help.html:685 -#: warehouse/templates/pages/help.html:693 -#: warehouse/templates/pages/help.html:704 -#: warehouse/templates/pages/help.html:721 -#: warehouse/templates/pages/help.html:728 -#: warehouse/templates/pages/help.html:736 +#: warehouse/templates/pages/help.html:696 +#: warehouse/templates/pages/help.html:701 +#: warehouse/templates/pages/help.html:709 +#: warehouse/templates/pages/help.html:720 +#: warehouse/templates/pages/help.html:737 +#: warehouse/templates/pages/help.html:744 #: warehouse/templates/pages/help.html:752 -#: warehouse/templates/pages/help.html:757 -#: warehouse/templates/pages/help.html:762 -#: warehouse/templates/pages/help.html:772 -#: warehouse/templates/pages/help.html:781 -#: warehouse/templates/pages/help.html:795 -#: warehouse/templates/pages/help.html:803 +#: warehouse/templates/pages/help.html:768 +#: warehouse/templates/pages/help.html:773 +#: warehouse/templates/pages/help.html:778 +#: warehouse/templates/pages/help.html:788 +#: warehouse/templates/pages/help.html:797 #: warehouse/templates/pages/help.html:811 #: warehouse/templates/pages/help.html:819 -#: warehouse/templates/pages/help.html:829 -#: warehouse/templates/pages/help.html:844 -#: warehouse/templates/pages/help.html:859 +#: warehouse/templates/pages/help.html:827 +#: warehouse/templates/pages/help.html:835 +#: warehouse/templates/pages/help.html:845 #: warehouse/templates/pages/help.html:860 -#: warehouse/templates/pages/help.html:861 -#: warehouse/templates/pages/help.html:862 -#: warehouse/templates/pages/help.html:867 +#: warehouse/templates/pages/help.html:875 +#: warehouse/templates/pages/help.html:876 +#: warehouse/templates/pages/help.html:877 +#: warehouse/templates/pages/help.html:878 +#: warehouse/templates/pages/help.html:883 #: warehouse/templates/pages/security.html:36 #: warehouse/templates/pages/sponsors.html:33 #: warehouse/templates/pages/sponsors.html:37 @@ -458,7 +460,7 @@ msgstr "" #: warehouse/templates/base.html:41 warehouse/templates/base.html:55 #: warehouse/templates/base.html:265 #: warehouse/templates/includes/current-user-indicator.html:55 -#: warehouse/templates/pages/help.html:103 +#: warehouse/templates/pages/help.html:105 #: warehouse/templates/pages/sitemap.html:27 msgid "Help" msgstr "" @@ -1646,7 +1648,7 @@ msgstr "" #: warehouse/templates/includes/packaging/project-data.html:84 #: warehouse/templates/includes/packaging/project-data.html:86 -#: warehouse/templates/pages/help.html:557 +#: warehouse/templates/pages/help.html:560 msgid "Maintainer:" msgstr "" @@ -3006,7 +3008,7 @@ msgid "" msgstr "" #: warehouse/templates/manage/roles.html:39 -#: warehouse/templates/pages/help.html:556 +#: warehouse/templates/pages/help.html:559 msgid "There are two possible roles for collaborators:" msgstr "" @@ -3815,104 +3817,110 @@ msgid "" "project?" msgstr "" -#: warehouse/templates/pages/help.html:86 +#: warehouse/templates/pages/help.html:85 +msgid "" +"Where does PyPI get its data on project vulnerabilities from, and how can" +" I correct it?" +msgstr "" + +#: warehouse/templates/pages/help.html:88 msgid "" "Why am I getting a \"Filename or contents already exists\" or \"Filename " "has been previously used\" error?" msgstr "" -#: warehouse/templates/pages/help.html:87 +#: warehouse/templates/pages/help.html:89 msgid "Why isn't my desired project name available?" msgstr "" -#: warehouse/templates/pages/help.html:88 +#: warehouse/templates/pages/help.html:90 msgid "How do I claim an abandoned or previously registered project name?" msgstr "" -#: warehouse/templates/pages/help.html:89 +#: warehouse/templates/pages/help.html:91 msgid "What collaborator roles are available for a project on PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:90 +#: warehouse/templates/pages/help.html:92 msgid "How do I become an owner/maintainer of a project on PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:91 +#: warehouse/templates/pages/help.html:93 msgid "How can I upload a project description in a different format?" msgstr "" -#: warehouse/templates/pages/help.html:92 +#: warehouse/templates/pages/help.html:94 msgid "How do I request a new trove classifier?" msgstr "" -#: warehouse/templates/pages/help.html:93 +#: warehouse/templates/pages/help.html:95 msgid "Where can I report a bug or provide feedback about PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:95 +#: warehouse/templates/pages/help.html:97 msgid "Who maintains PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:96 +#: warehouse/templates/pages/help.html:98 msgid "What powers PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:97 +#: warehouse/templates/pages/help.html:99 msgid "Can I depend on PyPI being available?" msgstr "" -#: warehouse/templates/pages/help.html:98 +#: warehouse/templates/pages/help.html:100 msgid "How can I contribute to PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:99 +#: warehouse/templates/pages/help.html:101 msgid "How do I keep up with upcoming changes to PyPI?" msgstr "" -#: warehouse/templates/pages/help.html:100 +#: warehouse/templates/pages/help.html:102 msgid "" "What does the \"beta feature\" badge mean? What are Warehouse's current " "beta features?" msgstr "" -#: warehouse/templates/pages/help.html:101 +#: warehouse/templates/pages/help.html:103 msgid "How do I pronounce \"PyPI\"?" msgstr "" -#: warehouse/templates/pages/help.html:108 +#: warehouse/templates/pages/help.html:110 msgid "Common questions" msgstr "" -#: warehouse/templates/pages/help.html:111 -#: warehouse/templates/pages/help.html:192 +#: warehouse/templates/pages/help.html:113 +#: warehouse/templates/pages/help.html:195 msgid "Basics" msgstr "" -#: warehouse/templates/pages/help.html:122 +#: warehouse/templates/pages/help.html:124 msgid "My Account" msgstr "" -#: warehouse/templates/pages/help.html:139 -#: warehouse/templates/pages/help.html:512 +#: warehouse/templates/pages/help.html:141 +#: warehouse/templates/pages/help.html:515 msgid "Integrating" msgstr "" -#: warehouse/templates/pages/help.html:149 -#: warehouse/templates/pages/help.html:539 +#: warehouse/templates/pages/help.html:151 +#: warehouse/templates/pages/help.html:542 msgid "Administration of projects on PyPI" msgstr "" -#: warehouse/templates/pages/help.html:163 -#: warehouse/templates/pages/help.html:609 +#: warehouse/templates/pages/help.html:166 +#: warehouse/templates/pages/help.html:625 msgid "Troubleshooting" msgstr "" -#: warehouse/templates/pages/help.html:179 -#: warehouse/templates/pages/help.html:748 +#: warehouse/templates/pages/help.html:182 +#: warehouse/templates/pages/help.html:764 msgid "About" msgstr "" -#: warehouse/templates/pages/help.html:195 +#: warehouse/templates/pages/help.html:198 #, python-format msgid "" "\n" @@ -3936,7 +3944,7 @@ msgid "" " " msgstr "" -#: warehouse/templates/pages/help.html:204 +#: warehouse/templates/pages/help.html:207 #, python-format msgid "" "To learn how to install a file from PyPI, visit the Python Packaging User Guide." msgstr "" -#: warehouse/templates/pages/help.html:211 +#: warehouse/templates/pages/help.html:214 #, python-format msgid "" "For full instructions on configuring, packaging and distributing your " @@ -3956,7 +3964,7 @@ msgid "" "target=\"_blank\" rel=\"noopener\">Python Packaging User Guide." msgstr "" -#: warehouse/templates/pages/help.html:218 +#: warehouse/templates/pages/help.html:221 #, python-format msgid "" "Classifiers are used to categorize projects on PyPI. See PyPI itself has not suffered a breach. This is a protective measure " @@ -4044,7 +4052,7 @@ msgid "" "href=\"%(reset_pwd_href)s\">reset your password.
" msgstr "" -#: warehouse/templates/pages/help.html:280 +#: warehouse/templates/pages/help.html:283 #, python-format msgid "" "All PyPI user events are stored under security history in account " @@ -4054,7 +4062,7 @@ msgid "" "href=\"mailto:%(admin_email)s\">%(admin_email)s
" msgstr "" -#: warehouse/templates/pages/help.html:292 +#: warehouse/templates/pages/help.html:295 msgid "" "A PyPI API token linked to your account was posted on a public " "website. It was automatically revoked, but before regenerating a new one," @@ -4063,7 +4071,7 @@ msgid "" "applies too.
" msgstr "" -#: warehouse/templates/pages/help.html:302 +#: warehouse/templates/pages/help.html:305 #, python-format msgid "" "Two factor authentication (2FA) makes your account more secure by " @@ -4082,7 +4090,7 @@ msgid "" "rel=\"noopener\">discuss.python.org.
" msgstr "" -#: warehouse/templates/pages/help.html:329 +#: warehouse/templates/pages/help.html:332 #, python-format msgid "" "PyPI users can set up two-factor authentication using any authentication " @@ -4091,21 +4099,21 @@ msgid "" "password\">TOTP standard." msgstr "" -#: warehouse/templates/pages/help.html:330 +#: warehouse/templates/pages/help.html:333 msgid "" "TOTP authentication " "applications generate a regularly changing authentication code to use " "when logging into your account." msgstr "" -#: warehouse/templates/pages/help.html:331 +#: warehouse/templates/pages/help.html:334 msgid "" "Because TOTP is an " "open standard, there are many applications that are compatible with your " "PyPI account. Popular applications include:" msgstr "" -#: warehouse/templates/pages/help.html:334 +#: warehouse/templates/pages/help.html:337 #, python-format msgid "" "Google Authenticator for iOS" msgstr "" -#: warehouse/templates/pages/help.html:337 -#: warehouse/templates/pages/help.html:339 -#: warehouse/templates/pages/help.html:344 -#: warehouse/templates/pages/help.html:346 +#: warehouse/templates/pages/help.html:340 +#: warehouse/templates/pages/help.html:342 +#: warehouse/templates/pages/help.html:347 +#: warehouse/templates/pages/help.html:349 msgid "(proprietary)" msgstr "" -#: warehouse/templates/pages/help.html:341 +#: warehouse/templates/pages/help.html:344 #, python-format msgid "" "Duo Mobile for iOS" msgstr "" -#: warehouse/templates/pages/help.html:347 -#: warehouse/templates/pages/help.html:348 +#: warehouse/templates/pages/help.html:350 +#: warehouse/templates/pages/help.html:351 msgid "(open source)" msgstr "" -#: warehouse/templates/pages/help.html:352 +#: warehouse/templates/pages/help.html:355 #, python-format msgid "" "Some password managers (e.g. 2FA with an " "authentication application:" msgstr "" -#: warehouse/templates/pages/help.html:362 +#: warehouse/templates/pages/help.html:365 msgid "" "Open an authentication (TOTP) application" msgstr "" -#: warehouse/templates/pages/help.html:363 +#: warehouse/templates/pages/help.html:366 msgid "" "Log in to your PyPI account, go to your account settings, and choose " "\"Add 2FA with " "authentication application\"" msgstr "" -#: warehouse/templates/pages/help.html:364 +#: warehouse/templates/pages/help.html:367 msgid "" "PyPI will generate a secret key, specific to your account. This is " "displayed as a QR code, and as a text code." msgstr "" -#: warehouse/templates/pages/help.html:365 +#: warehouse/templates/pages/help.html:368 msgid "" "Scan the QR code with your authentication application, or type it in " "manually. The method of input will depend on the application you have " "chosen." msgstr "" -#: warehouse/templates/pages/help.html:366 +#: warehouse/templates/pages/help.html:369 msgid "" "Your application will generate an authentication code - use this to " "verify your set up on PyPI" msgstr "" -#: warehouse/templates/pages/help.html:369 +#: warehouse/templates/pages/help.html:372 msgid "" "The PyPI server and your application now share your PyPI secret key, " "allowing your application to generate valid authentication codes for your" " PyPI account." msgstr "" -#: warehouse/templates/pages/help.html:371 -#: warehouse/templates/pages/help.html:413 +#: warehouse/templates/pages/help.html:374 +#: warehouse/templates/pages/help.html:416 msgid "Next time you log in to PyPI you'll need to:" msgstr "" -#: warehouse/templates/pages/help.html:373 -#: warehouse/templates/pages/help.html:465 +#: warehouse/templates/pages/help.html:376 +#: warehouse/templates/pages/help.html:468 msgid "Provide your username and password, as normal" msgstr "" -#: warehouse/templates/pages/help.html:374 +#: warehouse/templates/pages/help.html:377 msgid "Open your authentication application to generate an authentication code" msgstr "" -#: warehouse/templates/pages/help.html:375 +#: warehouse/templates/pages/help.html:378 msgid "Use this code to finish logging into PyPI" msgstr "" -#: warehouse/templates/pages/help.html:381 +#: warehouse/templates/pages/help.html:384 msgid "" "A security device is a USB key or other " "device that generates a one-time password and sends that password to " @@ -4215,11 +4223,11 @@ msgid "" "user." msgstr "" -#: warehouse/templates/pages/help.html:383 +#: warehouse/templates/pages/help.html:386 msgid "To set up two factor authentication with a USB key, you'll need:" msgstr "" -#: warehouse/templates/pages/help.html:385 +#: warehouse/templates/pages/help.html:388 #, python-format msgid "" "To use a :" msgstr "" -#: warehouse/templates/pages/help.html:390 +#: warehouse/templates/pages/help.html:393 #, python-format msgid "" "Popular keys include Thetis." msgstr "" -#: warehouse/templates/pages/help.html:397 +#: warehouse/templates/pages/help.html:400 msgid "" "Note that some older Yubico USB keys do not follow the FIDO " "specification, and will therefore not work with PyPI" msgstr "" -#: warehouse/templates/pages/help.html:402 +#: warehouse/templates/pages/help.html:405 msgid "Follow these steps:" msgstr "" -#: warehouse/templates/pages/help.html:404 +#: warehouse/templates/pages/help.html:407 msgid "" "\n" "__token__
"
msgstr ""
-#: warehouse/templates/pages/help.html:491
+#: warehouse/templates/pages/help.html:494
msgid ""
"Set your password to the token value, including the pypi-
"
"prefix"
msgstr ""
-#: warehouse/templates/pages/help.html:495
+#: warehouse/templates/pages/help.html:498
#, python-format
msgid ""
"Where you edit or add these values will depend on your individual use "
@@ -4437,14 +4445,14 @@ msgid ""
"rel=\"noopener\">.travis.yml
if you are using Travis)."
msgstr ""
-#: warehouse/templates/pages/help.html:499
+#: warehouse/templates/pages/help.html:502
msgid ""
"Advanced users may wish to inspect their token by decoding it with "
"base64, and checking the output against the unique identifier displayed "
"on PyPI."
msgstr ""
-#: warehouse/templates/pages/help.html:503
+#: warehouse/templates/pages/help.html:506
msgid ""
"\n"
" PyPI asks you to confirm your password before you want to "
@@ -4458,15 +4466,15 @@ msgid ""
" "
msgstr ""
-#: warehouse/templates/pages/help.html:515
+#: warehouse/templates/pages/help.html:518
msgid "Yes, including RSS feeds of new packages and new releases."
msgstr ""
-#: warehouse/templates/pages/help.html:515
+#: warehouse/templates/pages/help.html:518
msgid "See the API reference."
msgstr ""
-#: warehouse/templates/pages/help.html:518
+#: warehouse/templates/pages/help.html:521
#, python-format
msgid ""
"If you need to run your own mirror of PyPI, the GitHub apps."
msgstr ""
-#: warehouse/templates/pages/help.html:524
+#: warehouse/templates/pages/help.html:527
#, python-format
msgid ""
"You can analyze PyPI project/package metadata and via our public dataset on Google BigQuery."
msgstr ""
-#: warehouse/templates/pages/help.html:526
+#: warehouse/templates/pages/help.html:529
#, python-format
msgid ""
"other relevant factors."
msgstr ""
-#: warehouse/templates/pages/help.html:535
+#: warehouse/templates/pages/help.html:538
#, python-format
msgid ""
"For recent statistics on uptime and performance, see ."
msgstr ""
-#: warehouse/templates/pages/help.html:542
+#: warehouse/templates/pages/help.html:545
#, python-format
msgid ""
"PyPI does not support publishing private packages. If you need to publish"
@@ -4525,7 +4533,7 @@ msgid ""
"run your own deployment of the devpi project."
msgstr ""
-#: warehouse/templates/pages/help.html:545
+#: warehouse/templates/pages/help.html:548
msgid ""
"Your publishing tool may return an error that your new project can't be "
"created with your desired name, despite no evidence of a project or "
@@ -4533,7 +4541,7 @@ msgid ""
"reasons this may occur:"
msgstr ""
-#: warehouse/templates/pages/help.html:547
+#: warehouse/templates/pages/help.html:550
#, python-format
msgid ""
"The project name conflicts with a module from any major version from 2.5 to present."
msgstr ""
-#: warehouse/templates/pages/help.html:548
+#: warehouse/templates/pages/help.html:551
#, python-format
msgid ""
"The project name has been explicitly prohibited by the PyPI "
@@ -4550,13 +4558,13 @@ msgid ""
"with a malicious package."
msgstr ""
-#: warehouse/templates/pages/help.html:549
+#: warehouse/templates/pages/help.html:552
msgid ""
"The project name has been registered by another user, but no releases "
"have been created."
msgstr ""
-#: warehouse/templates/pages/help.html:553
+#: warehouse/templates/pages/help.html:556
#, python-format
msgid ""
"Follow the PEP 541."
msgstr ""
-#: warehouse/templates/pages/help.html:557
+#: warehouse/templates/pages/help.html:560
msgid ""
"Can upload releases for a package. Cannot add collaborators. Cannot "
"delete files, releases, or the project."
msgstr ""
-#: warehouse/templates/pages/help.html:558
+#: warehouse/templates/pages/help.html:561
msgid "Owner:"
msgstr ""
-#: warehouse/templates/pages/help.html:558
+#: warehouse/templates/pages/help.html:561
msgid ""
"Can upload releases. Can add other collaborators. Can delete files, "
"releases, or the entire project."
msgstr ""
-#: warehouse/templates/pages/help.html:561
+#: warehouse/templates/pages/help.html:564
msgid ""
"Only the current owners of a project have the ability to add new owners "
"or maintainers. If you need to request ownership, you should contact the "
@@ -4589,12 +4597,12 @@ msgid ""
"project page."
msgstr ""
-#: warehouse/templates/pages/help.html:562
+#: warehouse/templates/pages/help.html:565
#, python-format
msgid "If the owner is unresponsive, see %(anchor_text)s"
msgstr ""
-#: warehouse/templates/pages/help.html:565
+#: warehouse/templates/pages/help.html:568
#, python-format
msgid ""
"By default, an upload's description will render with file an issue and tell us:"
msgstr ""
-#: warehouse/templates/pages/help.html:580
-#: warehouse/templates/pages/help.html:601
+#: warehouse/templates/pages/help.html:583
+#: warehouse/templates/pages/help.html:604
msgid "A link to your project on PyPI (or Test PyPI)"
msgstr ""
-#: warehouse/templates/pages/help.html:581
+#: warehouse/templates/pages/help.html:584
msgid "The size of your release, in megabytes"
msgstr ""
-#: warehouse/templates/pages/help.html:582
+#: warehouse/templates/pages/help.html:585
msgid "Which index/indexes you need the increase for (PyPI, Test PyPI, or both)"
msgstr ""
-#: warehouse/templates/pages/help.html:583
-#: warehouse/templates/pages/help.html:603
+#: warehouse/templates/pages/help.html:586
+#: warehouse/templates/pages/help.html:606
msgid ""
"A brief description of your project, including the reason for the "
"additional size."
msgstr ""
-#: warehouse/templates/pages/help.html:589
+#: warehouse/templates/pages/help.html:592
msgid ""
"If you can't upload your project's release to PyPI because you're hitting"
" the project size limit, first remove any unnecessary releases or "
"individual files to lower your overall project size."
msgstr ""
-#: warehouse/templates/pages/help.html:596
+#: warehouse/templates/pages/help.html:599
#, python-format
msgid ""
"If that is not possible, we can sometimes increase your limit. File an issue and tell us:"
msgstr ""
-#: warehouse/templates/pages/help.html:602
+#: warehouse/templates/pages/help.html:605
msgid "The total size of your project, in gigabytes"
msgstr ""
#: warehouse/templates/pages/help.html:612
+#, python-format
+msgid ""
+"PyPI receives reports on vulnerabilities in the packages hosted on it "
+"from the Open Source Vulnerabilities project, which in turn "
+"ingests vulnerabilities from the Python Packaging "
+"Advisory Database."
+msgstr ""
+
+#: warehouse/templates/pages/help.html:617
+#, python-format
+msgid ""
+"If you believe vulnerability data for your project is invalid or "
+"incorrect, file an issue with details."
+msgstr ""
+
+#: warehouse/templates/pages/help.html:628
msgid ""
"If you've forgotten your PyPI password but you remember your email "
"address or username, follow these steps to reset your password:"
msgstr ""
-#: warehouse/templates/pages/help.html:614
+#: warehouse/templates/pages/help.html:630
#, python-format
msgid "Go to reset your password."
msgstr ""
-#: warehouse/templates/pages/help.html:615
+#: warehouse/templates/pages/help.html:631
msgid "Enter the email address or username you used for PyPI and submit the form."
msgstr ""
-#: warehouse/templates/pages/help.html:616
+#: warehouse/templates/pages/help.html:632
msgid "You'll receive an email with a password reset link."
msgstr ""
-#: warehouse/templates/pages/help.html:621
+#: warehouse/templates/pages/help.html:637
msgid "If you've lost access to your PyPI account due to:"
msgstr ""
-#: warehouse/templates/pages/help.html:623
+#: warehouse/templates/pages/help.html:639
msgid "Lost access to the email address associated with your account"
msgstr ""
-#: warehouse/templates/pages/help.html:624
+#: warehouse/templates/pages/help.html:640
msgid ""
"Lost two factor authentication application, device, and recovery "
"codes"
msgstr ""
-#: warehouse/templates/pages/help.html:627
+#: warehouse/templates/pages/help.html:643
#, python-format
msgid ""
"You can proceed to API Token for uploads:"
msgstr ""
-#: warehouse/templates/pages/help.html:641
+#: warehouse/templates/pages/help.html:657
msgid "Ensure that your API Token is valid and has not been revoked."
msgstr ""
-#: warehouse/templates/pages/help.html:642
+#: warehouse/templates/pages/help.html:658
msgid ""
"Ensure that your API Token is properly "
"formatted and does not contain any trailing characters such as "
"newlines."
msgstr ""
-#: warehouse/templates/pages/help.html:644
+#: warehouse/templates/pages/help.html:660
msgid ""
"In both cases, remember that PyPI and TestPyPI each require you to create"
" an account, so your credentials may be different."
msgstr ""
-#: warehouse/templates/pages/help.html:646
+#: warehouse/templates/pages/help.html:662
msgid ""
"\n"
" If you're using Windows and trying to paste your password or "
@@ -4762,7 +4789,7 @@ msgid ""
" "
msgstr ""
-#: warehouse/templates/pages/help.html:650
+#: warehouse/templates/pages/help.html:666
#, python-format
msgid ""
"This is a Learn why on the PSF blog."
msgstr ""
-#: warehouse/templates/pages/help.html:664
+#: warehouse/templates/pages/help.html:680
#, python-format
msgid ""
"If you are having trouble with
+ {% trans trimmed osv_href='https://osv.dev/', title=gettext('External link'), vulns_href='https://github.com/pypa/advisory-db' %}
+ PyPI receives reports on vulnerabilities in the packages hosted on it from the Open Source Vulnerabilities project, which in turn ingests vulnerabilities from the Python Packaging Advisory Database.
+ {% endtrans %}
+
+ {% trans trimmed file_issue_href='https://github.com/pypa/advisory-db/issues', title=gettext('External link') %}
+ If you believe vulnerability data for your project is invalid or incorrect, file an issue with details.
+ {% endtrans %}
+ %(command)s
and get a "
@@ -4791,7 +4818,7 @@ msgid ""
"information:"
msgstr ""
-#: warehouse/templates/pages/help.html:666
+#: warehouse/templates/pages/help.html:682
msgid ""
"If you see an error like There was a problem confirming the ssl "
"certificate
or tlsv1 alert protocol version
or "
@@ -4799,7 +4826,7 @@ msgid ""
"PyPI with a newer TLS support library."
msgstr ""
-#: warehouse/templates/pages/help.html:667
+#: warehouse/templates/pages/help.html:683
msgid ""
"The specific steps you need to take will depend on your operating system "
"version, where your installation of Python originated (python.org, your "
@@ -4807,7 +4834,7 @@ msgid ""
" Python, setuptools
, and pip
."
msgstr ""
-#: warehouse/templates/pages/help.html:669
+#: warehouse/templates/pages/help.html:685
#, python-format
msgid ""
"For help, go to %(command)s."
msgstr ""
-#: warehouse/templates/pages/help.html:680
+#: warehouse/templates/pages/help.html:696
#, python-format
msgid ""
"We take , so we can try to fix the problem, for you and others."
msgstr ""
-#: warehouse/templates/pages/help.html:693
+#: warehouse/templates/pages/help.html:709
#, python-format
msgid ""
"In a previous version of PyPI, it used to be possible for maintainers to "
@@ -4846,7 +4873,7 @@ msgid ""
"rel=\"noopener\">use twine to upload your project to PyPI."
msgstr ""
-#: warehouse/templates/pages/help.html:702
+#: warehouse/templates/pages/help.html:718
msgid ""
"Spammers return to PyPI with some regularity hoping to place their Search"
" Engine Optimized phishing, scam, and click-farming content on the site. "
@@ -4855,7 +4882,7 @@ msgid ""
"prime target."
msgstr ""
-#: warehouse/templates/pages/help.html:704
+#: warehouse/templates/pages/help.html:720
#, python-format
msgid ""
"When the PyPI administrators are overwhelmed by spam or "
@@ -4866,29 +4893,29 @@ msgid ""
"have updated it with reasoning for the intervention."
msgstr ""
-#: warehouse/templates/pages/help.html:713
+#: warehouse/templates/pages/help.html:729
msgid "PyPI will return these errors for one of these reasons:"
msgstr ""
-#: warehouse/templates/pages/help.html:715
+#: warehouse/templates/pages/help.html:731
msgid "Filename has been used and file exists"
msgstr ""
-#: warehouse/templates/pages/help.html:716
+#: warehouse/templates/pages/help.html:732
msgid "Filename has been used but file no longer exists"
msgstr ""
-#: warehouse/templates/pages/help.html:717
+#: warehouse/templates/pages/help.html:733
msgid "A file with the exact same content exists"
msgstr ""
-#: warehouse/templates/pages/help.html:719
+#: warehouse/templates/pages/help.html:735
msgid ""
"PyPI does not allow for a filename to be reused, even once a project has "
"been deleted and recreated."
msgstr ""
-#: warehouse/templates/pages/help.html:721
+#: warehouse/templates/pages/help.html:737
#, python-format
msgid ""
"To avoid this situation, pypi.org."
msgstr ""
-#: warehouse/templates/pages/help.html:728
+#: warehouse/templates/pages/help.html:744
#, python-format
msgid ""
"If you would like to request a new trove classifier file a pull request "
@@ -4906,7 +4933,7 @@ msgid ""
" to include a brief justification of why it is important."
msgstr ""
-#: warehouse/templates/pages/help.html:736
+#: warehouse/templates/pages/help.html:752
#, python-format
msgid ""
"If you're experiencing an issue with PyPI itself, we welcome "
@@ -4917,14 +4944,14 @@ msgid ""
" first check that a similar issue does not already exist."
msgstr ""
-#: warehouse/templates/pages/help.html:743
+#: warehouse/templates/pages/help.html:759
msgid ""
"If you are having an issue is with a specific package installed from "
"PyPI, you should reach out to the maintainers of that project directly "
"instead."
msgstr ""
-#: warehouse/templates/pages/help.html:752
+#: warehouse/templates/pages/help.html:768
#, python-format
msgid ""
"PyPI is powered by the Warehouse project; ."
msgstr ""
-#: warehouse/templates/pages/help.html:779
+#: warehouse/templates/pages/help.html:795
msgid ""
"As of April 16, 2018, PyPI.org is at \"production\" status, meaning that "
"it has moved out of beta and replaced the old site (pypi.python.org). It "
"is now robust, tested, and ready for expected browser and API traffic."
msgstr ""
-#: warehouse/templates/pages/help.html:781
+#: warehouse/templates/pages/help.html:797
#, python-format
msgid ""
"PyPI is heavily cached and distributed via private index."
msgstr ""
-#: warehouse/templates/pages/help.html:795
+#: warehouse/templates/pages/help.html:811
#, python-format
msgid ""
"We have a huge amount of work to do to continue to maintain and improve "
@@ -4997,22 +5024,22 @@ msgid ""
"target=\"_blank\" rel=\"noopener\">the Warehouse project)."
msgstr ""
-#: warehouse/templates/pages/help.html:800
+#: warehouse/templates/pages/help.html:816
msgid "Financial:"
msgstr ""
-#: warehouse/templates/pages/help.html:800
+#: warehouse/templates/pages/help.html:816
#, python-format
msgid ""
"We would deeply appreciate your donations to fund "
"development and maintenance."
msgstr ""
-#: warehouse/templates/pages/help.html:801
+#: warehouse/templates/pages/help.html:817
msgid "Development:"
msgstr ""
-#: warehouse/templates/pages/help.html:801
+#: warehouse/templates/pages/help.html:817
msgid ""
"Warehouse is open source, and we would love to see some new faces working"
" on the project. You do not need to be an experienced "
@@ -5020,7 +5047,7 @@ msgid ""
" you make your first open source pull request!"
msgstr ""
-#: warehouse/templates/pages/help.html:803
+#: warehouse/templates/pages/help.html:819
#, python-format
msgid ""
"If you have skills in Python, ElasticSearch, HTML, SCSS, JavaScript, or "
@@ -5034,7 +5061,7 @@ msgid ""
"here."
msgstr ""
-#: warehouse/templates/pages/help.html:811
+#: warehouse/templates/pages/help.html:827
#, python-format
msgid ""
"Issues are grouped into Python packaging forum on Discourse."
msgstr ""
-#: warehouse/templates/pages/help.html:829
+#: warehouse/templates/pages/help.html:845
#, python-format
msgid ""
"Changes to PyPI are generally announced on both the {% trans %}Administration of projects on PyPI{% en
{{ project_size_limit() }}
{{ vulnerability_data() }}
+