@@ -778,6 +778,14 @@ directory containing the configuration file that specified them.
778778 - True to suppress visible warnings when a shebang launches an application
779779 other than a Python runtime.
780780
781+ * - ``source_settings ``
782+ - A mapping from source URL to settings specific to that index.
783+ When multiple configuration files include this section, URL settings are
784+ added or overwritten, but individual settings are not merged.
785+ These settings are currently only for :ref: `index signatures
786+ <pymanager-index-signatures>`.
787+
788+
781789.. _install-freethreaded-windows :
782790
783791Installing free-threaded binaries
@@ -799,6 +807,101 @@ installed, then ``python`` will launch this one. Otherwise, you will need to use
799807``py -V:3.14t ... `` or, if you have added the global aliases directory to your
800808:envvar: `PATH ` environment variable, the ``python3.14t.exe `` commands.
801809
810+
811+ .. _pymanager-index-signatures :
812+
813+ Index Signatures
814+ ----------------
815+
816+ .. versionadded :: 26.2
817+
818+ Index files may be signed to detect tampering. A signature is a catalog file
819+ at the same URL as the index with ``.cat `` added to the filename. The catalog
820+ file should contain the hash of its matching index file, and should be signed
821+ with a valid Authenticode signature. This allows standard tooling (on Windows)
822+ to generate a signature, and any certificate may be used as long as the client
823+ operating system already trusts its certification authority (root CA).
824+
825+ Index signatures are only downloaded and checked when the local configuration's
826+ ``source_settings `` section includes the index URL and ``requires_signature `` is
827+ true, or the index JSON contains ``requires_signature `` set to true. When the
828+ setting exists in local configuration, even when false, settings in the index
829+ are ignored.
830+
831+ As well as requiring a valid signature, the ``required_root_subject `` and
832+ ``required_publisher_subject `` settings can further restrict acceptable
833+ signatures based on the certificate Subject fields. Any attribute specified in
834+ the configuration must match the attribute in the certificate (additional
835+ attributes in the certificate are ignored). Typical attributes are ``CN= `` for
836+ the common name, ``O= `` for the organizational unit, and ``C= `` for the
837+ publisher's country.
838+
839+ Finally, the ``required_publisher_eku `` setting allows requiring that a specific
840+ Enhanced Key Usage (EKU) has been assigned to the publisher certificate. For
841+ example, the EKU ``1.3.6.1.5.5.7.3.3 `` indicates that the certificate was
842+ intended for code signing (as opposed to server or client authentication).
843+ In combination with a specific root CA, this provides another mechanism to
844+ verify a legitimate signature.
845+
846+ This is an example ``source_settings `` section from a configuration file. In
847+ this case, the publisher of the feed is uniquely identified by the combination
848+ of the Microsoft Identity Verification root and the EKU assigned by that root.
849+ The signature for this case would be found at
850+ ``https://www.python.org/ftp/python/index-windows.json.cat ``.
851+
852+ .. code :: json5
853+
854+ {
855+ "source_settings": {
856+ "https://www.python.org/ftp/python/index-windows.json": {
857+ "requires_signature": true,
858+ "required_root_subject": "CN=Microsoft Identity Verification Root Certificate Authority 2020",
859+ "required_publisher_subject": "CN=Python Software Foundation",
860+ "required_publisher_eku": "1.3.6.1.4.1.311.97.608394634.79987812.305991749.578777327"
861+ }
862+ }
863+ }
864+
865+ The same settings could be specified in the ``index.json `` file instead. In this
866+ case, the root and EKU are omitted, meaning that the signature must be valid and
867+ have a specific common name in the publisher's certificate, but no other checks
868+ are used.
869+
870+ .. code :: json5
871+
872+ {
873+ "requires_signature": true,
874+ "required_publisher_subject": "CN=Python Software Foundation",
875+ "versions": [
876+ // ...
877+ ]
878+ }
879+
880+ When settings from inside a feed are used, the user is notified and the settings
881+ are shown in the log file or verbose output. It is recommended to copy these
882+ settings into a local configuration file for feeds that will be used frequently,
883+ so that unauthorised modifications to the feed cannot disable verification.
884+
885+ It is not possible to override the location of the signature file in the feed or
886+ through a configuration file. Administrators can provide their own
887+ ``source_settings `` in a mandatory configuration file (see
888+ :ref: `pymanager-admin-config `).
889+
890+ If signature validation fails, you will be notified and prompted to continue.
891+ When interactive confirmation is not allowed (for example, because ``--yes `` was
892+ specified), it will always abort. To use a feed with invalid configuration in
893+ this scenario, you must provide a configuration file that disables signature
894+ checking for that feed.
895+
896+ .. code :: json5
897+
898+ "source_settings": {
899+ "https://www.example.com/feed-with-invalid-signature.json": {
900+ "requires_signature": false
901+ }
902+ }
903+
904+
802905 .. _pymanager-troubleshoot :
803906
804907Troubleshooting
0 commit comments