https://github.com/python/cpython/commit/b57b619e34cdfc87b47943c988b0b4d69f8f1fe4
commit: b57b619e34cdfc87b47943c988b0b4d69f8f1fe4
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-06-22T19:48:06Z
summary:
gh-135815: skip `netrc` security checks if `os.getuid` is missing (#135816)
files:
A Misc/NEWS.d/next/Library/2025-06-22-16-23-44.gh-issue-135815.0DandH.rst
M Doc/library/netrc.rst
M Lib/netrc.py
M Lib/test/test_netrc.py
diff --git a/Doc/library/netrc.rst b/Doc/library/netrc.rst
index f6260383b2b057..74c97e8c9a9759 100644
--- a/Doc/library/netrc.rst
+++ b/Doc/library/netrc.rst
@@ -24,12 +24,14 @@ the Unix :program:`ftp` program and other FTP clients.
a :exc:`FileNotFoundError` exception will be raised.
Parse errors will raise :exc:`NetrcParseError` with diagnostic
information including the file name, line number, and terminating token.
+
If no argument is specified on a POSIX system, the presence of passwords in
the :file:`.netrc` file will raise a :exc:`NetrcParseError` if the file
ownership or permissions are insecure (owned by a user other than the user
running the process, or accessible for read or write by any other user).
This implements security behavior equivalent to that of ftp and other
- programs that use :file:`.netrc`.
+ programs that use :file:`.netrc`. Such security checks are not available
+ on platforms that do not support :func:`os.getuid`.
.. versionchanged:: 3.4 Added the POSIX permission check.
diff --git a/Lib/netrc.py b/Lib/netrc.py
index b285fd8e357ddb..bd003e80a48081 100644
--- a/Lib/netrc.py
+++ b/Lib/netrc.py
@@ -7,6 +7,19 @@
__all__ = ["netrc", "NetrcParseError"]
+def _can_security_check():
+ # On WASI, getuid() is indicated as a stub but it may also be missing.
+ return os.name == 'posix' and hasattr(os, 'getuid')
+
+
+def _getpwuid(uid):
+ try:
+ import pwd
+ return pwd.getpwuid(uid)[0]
+ except (ImportError, LookupError):
+ return f'uid {uid}'
+
+
class NetrcParseError(Exception):
"""Exception raised on syntax errors in the .netrc file."""
def __init__(self, msg, filename=None, lineno=None):
@@ -142,18 +155,12 @@ def _parse(self, file, fp, default_netrc):
self._security_check(fp, default_netrc, self.hosts[entryname][0])
def _security_check(self, fp, default_netrc, login):
- if os.name == 'posix' and default_netrc and login != "anonymous":
+ if _can_security_check() and default_netrc and login != "anonymous":
prop = os.fstat(fp.fileno())
- if prop.st_uid != os.getuid():
- import pwd
- try:
- fowner = pwd.getpwuid(prop.st_uid)[0]
- except KeyError:
- fowner = 'uid %s' % prop.st_uid
- try:
- user = pwd.getpwuid(os.getuid())[0]
- except KeyError:
- user = 'uid %s' % os.getuid()
+ current_user_id = os.getuid()
+ if prop.st_uid != current_user_id:
+ fowner = _getpwuid(prop.st_uid)
+ user = _getpwuid(current_user_id)
raise NetrcParseError(
(f"~/.netrc file owner ({fowner}, {user}) does not match"
" current user"))
diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py
index 81e11a293cc4c8..9d720f627102e3 100644
--- a/Lib/test/test_netrc.py
+++ b/Lib/test/test_netrc.py
@@ -1,11 +1,7 @@
import netrc, os, unittest, sys, textwrap
+from test import support
from test.support import os_helper
-try:
- import pwd
-except ImportError:
- pwd = None
-
temp_filename = os_helper.TESTFN
class NetrcTestCase(unittest.TestCase):
@@ -269,9 +265,14 @@ def
test_comment_at_end_of_machine_line_pass_has_hash(self):
machine bar.domain.com login foo password pass
""", '#pass')
+ @unittest.skipUnless(support.is_wasi, 'WASI only test')
+ def test_security_on_WASI(self):
+ self.assertFalse(netrc._can_security_check())
+ self.assertEqual(netrc._getpwuid(0), 'uid 0')
+ self.assertEqual(netrc._getpwuid(123456), 'uid 123456')
@unittest.skipUnless(os.name == 'posix', 'POSIX only test')
- @unittest.skipIf(pwd is None, 'security check requires pwd module')
+ @unittest.skipUnless(hasattr(os, 'getuid'), "os.getuid is required")
@os_helper.skip_unless_working_chmod
def test_security(self):
# This test is incomplete since we are normally not run as root and
diff --git
a/Misc/NEWS.d/next/Library/2025-06-22-16-23-44.gh-issue-135815.0DandH.rst
b/Misc/NEWS.d/next/Library/2025-06-22-16-23-44.gh-issue-135815.0DandH.rst
new file mode 100644
index 00000000000000..0f4a68bf745a8e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-06-22-16-23-44.gh-issue-135815.0DandH.rst
@@ -0,0 +1,2 @@
+:mod:`netrc`: skip security checks if :func:`os.getuid` is missing.
+Patch by Bénédikt Tran.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]