Skip to content

Commit 6469b69

Browse files
committed
style: fix pre-existing pycodestyle violations across CVE-9.15 test files
24 violations had accumulated on the cve-9.15 branch from the #9901 and #9902 CVE-fix work and a couple of older spots. Surfaced when the full suite was run after the #9904 work; no functional change. - 22 x E501 (line too long > 79): - 15 in pgadmin/misc/file_manager/tests/test_filemanager_security.py (13 class declarations using two mixin parents, 2 docstrings) - 6 in pgadmin/utils/tests/test_session_file_format.py (5 class declarations, 1 docstring) - 1 in pgadmin/browser/tests/test_kerberos_with_mocking.py (extracted self.app.url_map._rules_by_endpoint into a local before the membership test) - 2 x E305 (expected 2 blank lines after class/function): - pgadmin/misc/file_manager/__init__.py (after _open_upload_target) - pgadmin/browser/__init__.py (after _first_form_error) Class declarations are wrapped via parenthesised continuation, the standard pgAdmin convention; docstrings are either shortened or wrapped across two lines preserving the same meaning. Verified: - pycodestyle clean project-wide (24 -> 0). - Affected tests still pass: test_filemanager_security 17/0/0, test_session_file_format 18/0/0, test_kerberos_with_mocking 2/0/3 (skips are pre-existing and unrelated -- Kerberos blueprint not loaded in default config).
1 parent 208541c commit 6469b69

5 files changed

Lines changed: 64 additions & 22 deletions

File tree

web/pgadmin/browser/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ def _first_form_error_message(form, default=None):
9191
if error:
9292
return str(error)
9393
return default
94+
95+
9496
PGADMIN_BROWSER = 'pgAdmin.Browser'
9597
PASS_ERROR_MSG = gettext('Your password has not been changed.')
9698
SMTP_SOCKET_ERROR = gettext(

web/pgadmin/browser/tests/test_kerberos_with_mocking.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ def setUp(self):
6666
# in setUp is too late to register the blueprint, so the failure
6767
# path that redirects to /kerberos/login would 500 with
6868
# BuildError. Skip when that endpoint isn't reachable.
69-
if 'authenticate.kerberos_login' not in self.app.url_map._rules_by_endpoint:
69+
endpoint_map = self.app.url_map._rules_by_endpoint
70+
if 'authenticate.kerberos_login' not in endpoint_map:
7071
self.skipTest(
7172
"Kerberos blueprint not loaded — set "
7273
"AUTHENTICATION_SOURCES=['kerberos'] in config_local.py at "

web/pgadmin/misc/file_manager/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def _open_upload_target(path):
6767
fd = os.open(path, flags, 0o600)
6868
return os.fdopen(fd, 'wb')
6969

70+
7071
MODULE_NAME = 'file_manager'
7172
global transid
7273

web/pgadmin/misc/file_manager/tests/test_filemanager_security.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ def make_symlink(self, link_name: str, target: str) -> str:
7575
# Positive — legitimate paths must continue to be allowed.
7676
# ---------------------------------------------------------------------------
7777

78-
class TestLegitPathInsideStorage(_CheckAccessPermissionMixin, BaseTestGenerator):
78+
class TestLegitPathInsideStorage(
79+
_CheckAccessPermissionMixin, BaseTestGenerator
80+
):
7981
"""A path entirely inside the storage dir must pass."""
8082

8183
scenarios = [('default', dict())]
@@ -85,7 +87,9 @@ def runTest(self):
8587
Filemanager.check_access_permission(self.in_dir, "/myfile.txt")
8688

8789

88-
class TestRelativeNotationResolvingInside(_CheckAccessPermissionMixin, BaseTestGenerator):
90+
class TestRelativeNotationResolvingInside(
91+
_CheckAccessPermissionMixin, BaseTestGenerator
92+
):
8993
"""A path with .. that resolves inside the sandbox must pass."""
9094

9195
scenarios = [('default', dict())]
@@ -97,7 +101,9 @@ def runTest(self):
97101
self.in_dir, "/subdir/../myfile.txt")
98102

99103

100-
class TestSymlinkedStorageRootPassesForRealChild(_CheckAccessPermissionMixin, BaseTestGenerator):
104+
class TestSymlinkedStorageRootPassesForRealChild(
105+
_CheckAccessPermissionMixin, BaseTestGenerator
106+
):
101107
"""If the storage root itself is a symlink, legitimate access still works.
102108
103109
Without realpath()ing in_dir, a symlinked storage root would compare
@@ -118,7 +124,9 @@ def runTest(self):
118124
Filemanager.check_access_permission(symlinked_root, "/legit.txt")
119125

120126

121-
class TestServerModeFalseSkipsCheck(_CheckAccessPermissionMixin, BaseTestGenerator):
127+
class TestServerModeFalseSkipsCheck(
128+
_CheckAccessPermissionMixin, BaseTestGenerator
129+
):
122130
"""SERVER_MODE=False: check is a no-op, allowing any path."""
123131

124132
scenarios = [('default', dict())]
@@ -135,7 +143,9 @@ def runTest(self):
135143
# Negative — escapes (symlinks and ..) must be rejected.
136144
# ---------------------------------------------------------------------------
137145

138-
class TestSymlinkPointingOutsideRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
146+
class TestSymlinkPointingOutsideRejected(
147+
_CheckAccessPermissionMixin, BaseTestGenerator
148+
):
139149
"""The core Vuln 2 fix: a symlink whose target is outside in_dir blocks."""
140150

141151
scenarios = [('default', dict())]
@@ -149,7 +159,9 @@ def runTest(self):
149159
self.in_dir, evil_path + "/victim.txt")
150160

151161

152-
class TestSymlinkAtLeafRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
162+
class TestSymlinkAtLeafRejected(
163+
_CheckAccessPermissionMixin, BaseTestGenerator
164+
):
153165
"""A symlink AS the leaf (not via intermediate) is also rejected."""
154166

155167
scenarios = [('default', dict())]
@@ -188,7 +200,9 @@ def runTest(self):
188200
# static method so the assertions are about the function behavior, not the
189201
# wiring — which is verified by reading the code in §4.2.3 / §4.2.4.
190202

191-
class TestRenameTargetSymlinkRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
203+
class TestRenameTargetSymlinkRejected(
204+
_CheckAccessPermissionMixin, BaseTestGenerator
205+
):
192206
"""rename's target path through a symlink → access denied."""
193207

194208
scenarios = [('default', dict())]
@@ -204,7 +218,9 @@ def runTest(self):
204218
self.in_dir, evil_path + "/renamed.txt")
205219

206220

207-
class TestDeleteTargetSymlinkRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
221+
class TestDeleteTargetSymlinkRejected(
222+
_CheckAccessPermissionMixin, BaseTestGenerator
223+
):
208224
"""delete's target path through a symlink → access denied."""
209225

210226
scenarios = [('default', dict())]
@@ -219,7 +235,9 @@ def runTest(self):
219235
Filemanager.check_access_permission(self.in_dir, evil_path)
220236

221237

222-
class TestDownloadTargetSymlinkRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
238+
class TestDownloadTargetSymlinkRejected(
239+
_CheckAccessPermissionMixin, BaseTestGenerator
240+
):
223241
"""download's target path through a symlink → access denied."""
224242

225243
scenarios = [('default', dict())]
@@ -234,7 +252,9 @@ def runTest(self):
234252
Filemanager.check_access_permission(self.in_dir, evil_path)
235253

236254

237-
class TestAddfolderTargetSymlinkRejected(_CheckAccessPermissionMixin, BaseTestGenerator):
255+
class TestAddfolderTargetSymlinkRejected(
256+
_CheckAccessPermissionMixin, BaseTestGenerator
257+
):
238258
"""addfolder's target path through a symlink → access denied."""
239259

240260
scenarios = [('default', dict())]
@@ -267,7 +287,9 @@ def tearDown(self):
267287
shutil.rmtree(self.tmpdir, ignore_errors=True)
268288

269289

270-
class TestOpenUploadTargetCreatesNewFile(_OpenUploadTargetMixin, BaseTestGenerator):
290+
class TestOpenUploadTargetCreatesNewFile(
291+
_OpenUploadTargetMixin, BaseTestGenerator
292+
):
271293
"""Positive: opening a non-existent path creates a regular file."""
272294

273295
scenarios = [('default', dict())]
@@ -282,8 +304,12 @@ def runTest(self):
282304
self.assertEqual(f.read(), b"hello")
283305

284306

285-
class TestOpenUploadTargetOverwritesRegularFile(_OpenUploadTargetMixin, BaseTestGenerator):
286-
"""Positive: opening over an existing regular file truncates and rewrites."""
307+
class TestOpenUploadTargetOverwritesRegularFile(
308+
_OpenUploadTargetMixin, BaseTestGenerator
309+
):
310+
"""Positive: opening over an existing regular file truncates and
311+
rewrites.
312+
"""
287313

288314
scenarios = [('default', dict())]
289315

@@ -299,7 +325,7 @@ def runTest(self):
299325

300326

301327
class TestOpenUploadTargetMode0600(_OpenUploadTargetMixin, BaseTestGenerator):
302-
"""Positive: newly-created upload files are mode 0o600 (intentional hardening).
328+
"""Positive: newly-created upload files are mode 0o600.
303329
304330
Documented behavior change vs. the umask-default 0o644 of the prior
305331
open(name, 'wb'). Release notes call this out.
@@ -320,7 +346,9 @@ def runTest(self):
320346
"Expected 0o600 (owner-only), got 0o%o" % mode)
321347

322348

323-
class TestOpenUploadTargetRejectsLeafSymlink(_OpenUploadTargetMixin, BaseTestGenerator):
349+
class TestOpenUploadTargetRejectsLeafSymlink(
350+
_OpenUploadTargetMixin, BaseTestGenerator
351+
):
324352
"""Negative: a pre-planted symlink at the leaf path raises ELOOP/EMLINK.
325353
326354
This is the TOCTOU-closing property: even if check_access_permission

web/pgadmin/utils/tests/test_session_file_format.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ def runTest(self):
193193
self.assertEqual(loaded.hmac_digest, sess.hmac_digest)
194194

195195

196-
class TestMultipleSessionsAreIndependent(_SessionTestSetupMixin, BaseTestGenerator):
196+
class TestMultipleSessionsAreIndependent(
197+
_SessionTestSetupMixin, BaseTestGenerator
198+
):
197199
"""Two sessions must not bleed data into each other."""
198200

199201
scenarios = [('default', dict())]
@@ -351,7 +353,9 @@ def runTest(self):
351353
self.assert_no_warning_logged("session file rejected")
352354

353355

354-
class TestCookieHmacMismatchWithValidFile(_SessionTestSetupMixin, BaseTestGenerator):
356+
class TestCookieHmacMismatchWithValidFile(
357+
_SessionTestSetupMixin, BaseTestGenerator
358+
):
355359
"""Spec T8: a legitimate file but a cookie that doesn't bind to it.
356360
357361
The file-HMAC verifies the file is server-written; the cookie-HMAC
@@ -375,7 +379,9 @@ def runTest(self):
375379
self.assert_no_warning_logged("session file rejected")
376380

377381

378-
class TestUnsafeSidReturnsNewSession(_SessionTestSetupMixin, BaseTestGenerator):
382+
class TestUnsafeSidReturnsNewSession(
383+
_SessionTestSetupMixin, BaseTestGenerator
384+
):
379385
"""A sid containing path-traversal characters yields safe_join None."""
380386

381387
scenarios = [('default', dict())]
@@ -411,8 +417,10 @@ def runTest(self):
411417
)
412418

413419

414-
class TestRealisticSessionShapeRoundTrip(_SessionTestSetupMixin, BaseTestGenerator):
415-
"""Round-trip a session with realistic pgAdmin contents (MFA, OAuth2, etc.).
420+
class TestRealisticSessionShapeRoundTrip(
421+
_SessionTestSetupMixin, BaseTestGenerator
422+
):
423+
"""Round-trip a session with realistic pgAdmin contents.
416424
417425
Spec test 7: MFA fields are JSON-safe but exercise them through put/get
418426
to confirm the format change preserves the data structures pgAdmin
@@ -509,7 +517,9 @@ def runTest(self):
509517
"got 0o%o" % new_mode)
510518

511519

512-
class TestServerModeFalseDirectUpload(_SessionTestSetupMixin, BaseTestGenerator):
520+
class TestServerModeFalseDirectUpload(
521+
_SessionTestSetupMixin, BaseTestGenerator
522+
):
513523
"""Spec T10: Scenario A chain closed at the session-read layer.
514524
515525
Even if SERVER_MODE=False permits an upload directly into the sessions

0 commit comments

Comments
 (0)