diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index be62e40..754ce40 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,6 +9,11 @@ jobs:
   build:
     runs-on: ubuntu-latest
 
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: ['3.9', '3.10', '3.11', '3.12']
+
     steps:
     - name: Clone access
       uses: actions/checkout@v4
@@ -21,10 +26,10 @@ jobs:
         repository: sdss/tree
         path: tree
 
-    - name: Set up Python 3.9
+    - name: Set up Python
       uses: actions/setup-python@v4
       with:
-        python-version: 3.9
+        python-version: ${{ matrix.python-version }}
 
     - name: Install tree package
       run: |
@@ -70,4 +75,4 @@ jobs:
     - name: Upload coverage to Codecov
       uses: codecov/codecov-action@v3
       with:
-        file: ./access/coverage.xml
\ No newline at end of file
+        file: ./access/coverage.xml
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b94f0b2..501a8c7 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,10 @@ Change Log
 
 This document records the main changes to the sdss_access code.
 
+3.0.5 (unreleased)
+------------------
+- PR `62` - Fix issue `61`: removed use of ``disutils`` which has been Deprecated in Python 3.12. Also pin Sphinx to ``<7.3.0`` to address `this issue <https://github.com/sphinx-doc/sphinx/issues/12339>`.
+
 3.0.4 (03-08-2024)
 ------------------
 - Fix issue `52` - rsync failure when remote file is compressed compared to template
diff --git a/python/sdss_access/sync/curl.py b/python/sdss_access/sync/curl.py
index 7bda080..bb6110e 100644
--- a/python/sdss_access/sync/curl.py
+++ b/python/sdss_access/sync/curl.py
@@ -1,8 +1,8 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 # The line above will help with 2to3 support.
 
-import distutils.spawn
 import re
+import shutil
 import time
 from os import popen
 from os.path import exists, dirname, join, basename, getsize, getmtime, sep
@@ -28,7 +28,7 @@ class CurlAccess(BaseAccess):
     def __init__(self, label='sdss_curl', stream_count=5, mirror=False, public=False, release=None,
                  verbose=False):
 
-        if not distutils.spawn.find_executable('curl'):
+        if not shutil.which('curl'):
             msg = ('cURL does not appear to be installed. To install, the cURL '
                    'download wizard is located at: https://curl.haxx.se/dlwiz/. '
                    'Installation tutorials for cURL (software from https://curl.haxx.se) '
diff --git a/setup.cfg b/setup.cfg
index b998db5..e70eb74 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -72,7 +72,7 @@ dev =
 	wheel>=0.33.6
 
 docs =
-	Sphinx>=7.1.0
+	Sphinx>=7.0.0,<7.3.0 # Pinning until this solved issue is tagged: https://github.com/sphinx-doc/sphinx/issues/12339
 	sphinx_bootstrap_theme>=0.4.12
 	recommonmark>=0.6
 	sphinx-issues>=1.2.0
diff --git a/tests/path/test_sdss5.py b/tests/path/test_sdss5.py
index 4c9660b..9b56c87 100644
--- a/tests/path/test_sdss5.py
+++ b/tests/path/test_sdss5.py
@@ -71,7 +71,7 @@ def test_special_function(self, path, name, special, keys, exp):
         assert exp in full
 
     @pytest.mark.parametrize('name, keys', [('specLite', ['fieldid', 'catalogid', 'run2d', 'mjd']),
-                                            ('mwmStar', ['component', 'sdss_id', 'v_astra']),])
+                                            ('mwmStar', ['sdss_id', 'v_astra']),])
     def test_lookup_keys(self, path, name, keys):
         realkeys = path.lookup_keys(name)
         assert set(keys) == set(realkeys)