Skip to content

[ADD] bpo-132142: --secure-root flag to SimpleHTTPRequestHandler to restrict file access #132224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

krishpranav
Copy link

@krishpranav krishpranav commented Apr 7, 2025

Summary

This pull request adds an optional --secure-root flag to the http.server module, specifically for SimpleHTTPRequestHandler. When enabled, this flag enforces that all requested paths must resolve within the specified base directory. If a requested file lies outside this directory — including via symbolic links — the server returns a 403 Forbidden response.

Implementation Details

  • Adds a secure_root parameter to SimpleHTTPRequestHandler, defaulting to False.
  • Updates translate_path() to enforce real path validation when secure_root is enabled.
  • Adds --secure-root CLI argument.
  • Integrates the feature into the http.server.test() entry point.
  • Maintains full backward compatibility and preserves current behavior when the flag is not used.

Examples:

Command:

python3 -m http.server --secure-root

Code:

import tempfile
import shutil
import threading
import urllib.request
import http.server
import os
import socket

class SecureRootTestCase(unittest.TestCase):
    def setUp(self):
        self.test_root = tempfile.mkdtemp()
        self.outside_file = os.path.join(tempfile.gettempdir(), "outside_secret.txt")
        with open(self.outside_file, "w") as f:
            f.write("TOP SECRET")

        self.symlink_path = os.path.join(self.test_root, "link.txt")
        try:
            os.symlink(self.outside_file, self.symlink_path)
        except (AttributeError, NotImplementedError, OSError):
            self.skipTest("Symlinks not supported on this platform")

        self.port = self._find_free_port()
        self.server_address = ("localhost", self.port)

        handler = functools.partial(http.server.SimpleHTTPRequestHandler,
                                    directory=self.test_root,
                                    secure_root=True)
        self.httpd = http.server.ThreadingHTTPServer(self.server_address, handler)

        self.thread = threading.Thread(target=self.httpd.serve_forever)
        self.thread.daemon = True
        self.thread.start()

    def tearDown(self):
        self.httpd.shutdown()
        self.thread.join()
        shutil.rmtree(self.test_root)
        try:
            os.remove(self.outside_file)
        except FileNotFoundError:
            pass

    def _find_free_port(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.bind(('localhost', 0))
            return s.getsockname()[1]

    def test_symlink_outside_root_is_forbidden(self):
        url = f"http://localhost:{self.port}/link.txt"
        with self.assertRaises(urllib.error.HTTPError) as cm:
            urllib.request.urlopen(url)

        self.assertEqual(cm.exception.code, 403)

Resolves: #132142

@python-cla-bot
Copy link

python-cla-bot bot commented Apr 7, 2025

The following commit authors need to sign the Contributor License Agreement:

CLA signed

@bedevere-app
Copy link

bedevere-app bot commented Apr 7, 2025

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@krishpranav krishpranav changed the title [ADD]: --secure-root flag to SimpleHTTPRequestHandler to restrict fil… [ADD] bpo-132142: --secure-root flag to SimpleHTTPRequestHandler to restrict file access Apr 7, 2025
@sobolevn sobolevn closed this Apr 7, 2025
@donBarbos
Copy link
Contributor

for the future I recommend you read the devguide before opening a PR. This is helpful and will give you some pointers on how best to get started

@krishpranav
Copy link
Author

Cool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Forbid SimpleHTTPRequestHandler serving files outside of specified directory
4 participants