Twine unequivocally refuses to use self-signed SSL certs:
- https://github.com/pypa/twine/issues/387
- https://github.com/pypa/twine/pull/463#issuecomment-556892003
- https://github.com/pypa/twine/issues/903
I genuinely can’t fathom how “switch to plain HTTP” would be a better recommendation over “let’s add a —trusted-host” (@jaraco’s comment on issue 387), but here we are.
Easy option: SSL cert bundle
You can pass --cert to Twine to specify a certificate bundle to use, but it has to include the entire certificate chain all the way back to the root CA! A typical “just pull the domain cert from the browser” does NOT give you this!
Second easy option: fork with support
Several forks of Twine exist which have added support for this feature, typically among others:
- https://github.com/strayge/twine-unofficial (seems like last maintained early 2023)
- there are of these but i closed all the tabs and can’t find them anymore :(
Monkey-patching out cert validation
You can also monkey-patch Twine to nuke its ability to verify SSL certificates.
Security hole
This is a bad idea, and if either of the two “easy” options work for you, you should definitely do that instead. This opens you up to man-in-the-middle attacks!
I blended together a monkey-patch from the closed-not-planned PR 463 and twine-unofficial to come up with this patch that seems to work (py 3.13):
import twine.repository
import twine.__main__
import urllib3
def kill_session_verify(self, *args, **kwargs):
self.session.verify = False
def install_hook():
twine.repository.Repository.set_certificate_authority = kill_session_verify
urllib3.disable_warnings()
def main():
install_hook()
twine.__main__.main()
if __name__ == '__main__':
main()Save this as something like twine_hacked.py and then call it instead of the twine module. Viola.