Skip to main content

Stars GitHub release License: MIT

[English | 中文]

In Python, all classes have a largely useless __subclasses__() method. This implementation not only incurs some memory overhead but also makes the code less secure. Users can access any built-in functions and classes through object.__subclasses__(), which undermines the complete security of exec and eval functions.
The no-subclasses library is designed to remove the __subclasses__() method from all classes, thereby reducing Python’s memory overhead and achieving almost complete security for exec and eval functions, preventing all __subclasses__ attacks within exec and eval.

Usage Example

By default, Python’s __subclasses__() can include almost any class. After enabling the no_subclasses library, __subclasses__() will always return an empty list, even if new classes are defined.

>>> import no_subclasses
>>> len(object.__subclasses__()) # Without no_subclasses library
313
>>> object.__subclasses__()[:5]
[<class 'type'>, <class 'async_generator'>, <class 'bytearray_iterator'>, <class 'bytearray'>, <class 'bytes_iterator'>]
>>>
>>> no_subclasses.init() # Enable no_subclasses library
>>> object.__subclasses__()
[]
>>> int.__subclasses__()
[]
>>> type.__subclasses__(type)
[]

Additionally, the library provides secure exec and eval functions, which cannot call any built-in functions or classes, nor can they be exploited by calling any class’s __subclasses__() method.

>>> from no_subclasses import init,safe_eval
>>>
>>> safe_scope = {"__builtins__":{}} # Cannot call any built-in functions
>>> attack_expr = "(1).__class__.__base__.__subclasses__()"
>>> eval(attack_expr,safe_scope) # eval before enabling no_subclasses
[<class 'type'>, <class 'async_generator'>, <class 'int'>,
<class 'bytearray_iterator'>, <class 'bytearray'>,
<class 'bytes_iterator'>, <class 'bytes'>,
<class 'PyCapsule'>,<class 'classmethod'>,...] # Contains many built-in functions, insecure
>>>
>>> init()
>>> safe_eval(attack_expr) # or eval(attack_expr,safe_scope)
[]

Detailed Usage

  • hack_class(cls): Clears the __subclasses__() list of a class.

  • hack_all_classes(start = object, ignored=()): Starting from a root class (default is object), clears the __subclasses__ list of all subclasses. ignored is a list or tuple of classes to be ignored, default is empty.

  • init_build_class_hook(): Modifies the built-in __build_class__ function so that executing a class statement does not modify the __subclasses__() list again, eliminating the need to re-call hack_class().

  • init_type_hook(): Modifies the built-in type() and type.__new__() so that calling type() or type.__new__() does not modify the __subclasses__() list again, eliminating the need to re-call hack_class(). (Requires pydetour library)

  • ``init()``: Initializes the entire no_subclasses library, calling hack_all_classes, init_build_class_hook, and init_type_hook together. (Recommended)

Implementation Principle

The hack_class method is implemented based on the lower-level pyobject library’s get_type_subclasses and set_type_subclasses methods. The hack_all_classes method uses BFS to deeply search all subclasses and then calls hack_class on each class.

Metadata

Release files for no-subclasses 1.0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for no-subclasses 1.0.2.1
File Size Uploaded Provenance
no_subclasses-1.0.2.1.tar.gz 5.9 kB Without provenance Details

Release files / no_subclasses-1.0.2.1.tar.gz

Download URL no_subclasses-1.0.2.1.tar.gz
Size 5.9 kB
Tags Source
SHA-256 checksum
How to use checksums
23e5f2acc276e59cb0f85a13c6c648ac3d25f6150e3313eb4266af5b46ecfd46
BLAKE2b-256 checksum
How to use checksums
cd8d308f17bdc19c5a8abc6b3df415545c97b7409d2ae5be0ed2805a024ae53d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Security for no-subclasses 1.0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.2.1 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page