Skip to content

Commit 8aa06db

Browse files
committed
updates
1 parent 54addac commit 8aa06db

9 files changed

Lines changed: 926 additions & 0 deletions

File tree

‎constructs/multiprocessing.md‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
title: Multiprocessing Module `Connection.recv()`
3+
short_title: Multiprocessing Module
4+
---
5+
6+
7+
The `multiprocessing` module provides powerful tools for inter-process communication (IPC) in Python. However, its use of the `pickle` module for serialization introduces significant security risks if not handled with care.
8+
9+
## Security Concerns
10+
11+
The `Connection.recv()` method (and its counterparts like `recv_bytes()`) automatically unpickles the received data. Deserializing untrusted data with `pickle` can lead to arbitrary code execution, making it a high-severity vulnerability when the source of the data cannot be fully trusted.
12+
13+
This risk exists because `pickle` is **not** a safe serialization format for untrusted input. Maliciously crafted data can trigger the execution of arbitrary Python code during unpickling.
14+
15+
Even when using `send()` / `recv()` pairs within the same application, design flaws (such as insufficient input validation or exposure of listening endpoints) can allow attackers to inject harmful payloads.
16+
17+
:::{important}
18+
The `multiprocessing` module **always** requires careful design, thorough code review, and robust security controls.
19+
:::
20+
21+
22+
## Preventive Measures
23+
24+
* **Use `Pipe()` where possible**: Connections created with `multiprocessing.Pipe()` are considered safer within a single process tree because both ends are typically controlled by the same application. Even then, treat data as untrusted.
25+
26+
+++
27+
28+
* **Implement strong authentication**: Before calling `recv()` on any `Connection` object (especially those from network listeners, queues, or shared resources), perform proper authentication of the remote process. This may include cryptographic verification, mutual TLS, or other access control mechanisms.
29+
30+
+++
31+
32+
* **Avoid `recv()` on untrusted connections**: Prefer safer alternatives such as:
33+
* Structured data formats like JSON, MessagePack (with schema validation), or Protocol Buffers.
34+
* Higher-level libraries that handle authentication and secure serialization.
35+
36+
+++
37+
38+
* **Sandbox or restrict privileges**: Run processes using the `multiprocessing` module with the principle of least privilege.
39+
40+
+++
41+
42+
* **Input validation**: Always validate and sanitise data *after* receiving but *before* any further processing, even if authentication is in place.
43+
44+
+++
45+
46+
* **Prefer `send_bytes()` / `recv_bytes()` with manual deserialization**: This gives you more control, though it does not eliminate the need for careful handling.
47+
48+
## Example
49+
50+
```python
51+
from multiprocessing import Pipe, Process
52+
53+
def worker(conn):
54+
# Good practice: send trusted data only
55+
conn.send({"command": "hello", "value": 42}) # Simple dict, safe
56+
57+
def main():
58+
parent_conn, child_conn = Pipe()
59+
p = Process(target=worker, args=(child_conn,))
60+
p.start()
61+
62+
# Safe because we control both ends and use Pipe()
63+
data = parent_conn.recv() # Still verify structure in production!
64+
print(data)
65+
66+
p.join()
67+
```
68+
69+
**Warning example (to avoid)**
70+
Dangerous example: receiving from an untrusted or network-exposed connection
71+
72+
```python
73+
conn = ... # from Listener or external source
74+
data = conn.recv() # Arbitrary code execution possible!
75+
```
76+
77+
## Discussion
78+
79+
The core issue stems from `pickle`'s design: it can execute code via `__reduce__` methods and other mechanisms. The Python documentation explicitly warns about this risk.
80+
81+
While `Pipe()` reduces the attack surface in simple cases, any exposure to external input, shared memory, or less-controlled process relationships reintroduces the danger. Modern Python security practices favour explicit, auditable serialization over `pickle` for cross-process or cross-machine communication.
82+
83+
Code audit tools relying on Python's `ast` module (without full type inference or data-flow analysis) can only detect common patterns. They may miss sophisticated uses of `multiprocessing.Connection` objects stored in variables or passed through helper functions.
84+
85+
## More Information
86+
87+
* [Python Documentation: multiprocessing](https://docs.python.org/3/library/multiprocessing.html#multiprocessing-recv-pickle-security)

‎constructs/pickle.md‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Pickle Function
2+
3+
:::{danger}
4+
Unpickling will import any class or function that it finds in the pickle data. This is a severe security concern as it permits the unpickler to import and invoke arbitrary code.
5+
6+
**Never use `pickle.load()`, `pickle.loads()` or `pickle.Unpickler` on data received from an untrusted or unauthenticated source.**
7+
:::
8+
9+
## Security Concerns
10+
11+
The security concern with the `pickle` module in Python revolves around **deserialisation of untrusted data**. When you use `pickle.load()` to deserialise a byte stream, the `pickle` module reconstructs Python objects from that stream by importing any class or function it encounters. A malicious attacker can craft a pickled payload that, when deserialised, can:
12+
13+
1. **Execute arbitrary code:** The `pickle` protocol can be manipulated to cause the deserialiser to import arbitrary modules and call arbitrary functions with arbitrary arguments. This permits an attacker to execute system commands, delete files, or perform any action the Python process running `pickle.load()` has permissions to carry out. This is commonly referred to as a "deserialisation vulnerability" or "arbitrary code execution."
14+
15+
2. **Cause Denial of Service (DoS):** An attacker could create a pickled object that, when deserialised, consumes excessive memory or CPU resources, leading to your application crashing or becoming unresponsive.
16+
17+
## Preventive Measures
18+
19+
The most effective preventive measure is to **avoid using `pickle` for deserialising untrusted data entirely**. Where this is not possible, consider the following approaches:
20+
21+
- **Use alternative serialisation formats:** Consider using `json`, `msgpack`, or `protobuf` for data exchange with untrusted sources. These formats are limited to data structures and do not support arbitrary code execution.
22+
23+
- **Implement cryptographic signing:** If you must use `pickle`, sign your pickled data with a cryptographic signature (e.g., using `hmac`) before transmission and verify the signature before deserialisation. This ensures the data has not been tampered with.
24+
25+
- **Run deserialisation in a sandbox:** Isolate the unpickling process in a restricted environment, such as a container or a separate process with limited system privileges.
26+
27+
- **Use `pickle.restricted` (Python 3.x):** The `pickle` module provides a `restricted` attribute that can be used to limit the classes and functions that can be imported during unpickling. However, this is not a complete security solution and should be used with caution.
28+
29+
## Example
30+
31+
Consider the following malicious pickled payload:
32+
33+
```python
34+
import pickle
35+
import os
36+
37+
class Malicious:
38+
def __reduce__(self):
39+
return (os.system, ('rm -rf /',))
40+
41+
malicious_data = pickle.dumps(Malicious())
42+
pickle.loads(malicious_data) # Executes 'rm -rf /'
43+
```
44+
45+
In this example, the `__reduce__` method returns a tuple instructing the unpickler to call `os.system` with the argument `'rm -rf /'`. When deserialised, this would execute a destructive system command.
46+
47+
## Discussion
48+
49+
The root cause of the security issue lies in Python's dynamic nature: `pickle` was designed for flexibility, allowing serialisation of complex Python objects, including functions and classes. This flexibility comes at the cost of security when handling untrusted data.
50+
51+
The security weakness is not in `pickle` itself but in how it is used. The Python documentation explicitly warns against using `pickle` with untrusted data.
52+
53+
54+
## More Information
55+
56+
- [Python `pickle` Documentation - Security Considerations](https://docs.python.org/3/library/pickle.html#pickle-restrict)

‎constructs/random.md‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Random Statement
2+
3+
:::{warning}
4+
The `random` module is **not** suitable for security or cryptographic purposes. Its pseudo-random number generator is deterministic and predictable if an attacker observes enough output. Never use it for generating session tokens, encryption keys, passwords, or any other security-sensitive values.
5+
:::
6+
7+
## Security Concerns
8+
9+
The `random` module in Python is unsafe for security or cryptographic purposes, such as generating session tokens, encryption keys, or passwords.
10+
11+
This is because the `random` module uses a pseudo-random number generator (PRNG) called the Mersenne Twister. This algorithm is **deterministic**—if an attacker can observe a sufficient amount of its output, they can completely determine its internal state (the seed) and accurately predict all future and even past values. This predictability can lead to severe vulnerabilities, including session hijacking, credential compromise, and unauthorised access.
12+
13+
The following `random` functions can introduce weaknesses when used in security contexts:
14+
- `random.seed`
15+
- `random.Random`
16+
- `random.randbytes`
17+
- `random.randint`
18+
- `random.random`
19+
- `random.randrange`
20+
- `random.triangular`
21+
- `random.uniform`
22+
23+
The `random` module is specifically designed for non-security-sensitive applications like simulations, statistical modelling, and simple games, prioritising speed and good statistical distribution over true unpredictability.
24+
25+
For all security-sensitive tasks, you **must** use the `secrets` module, which relies on a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) provided by the operating system.
26+
27+
## Preventive Measures
28+
29+
To avoid introducing predictable randomness vulnerabilities in your applications, follow these guidelines:
30+
31+
- **Use `secrets` for security purposes:** For any security-sensitive randomness—such as passwords, tokens, or cryptographic keys—always use the `secrets` module. This module provides functions like `secrets.token_bytes()`, `secrets.token_hex()`, and `secrets.choice()` that are designed for cryptographic security.
32+
33+
+++
34+
35+
36+
- **Use `random.SystemRandom` with caution:** The `SystemRandom` class uses `os.urandom()` and can be used as a drop-in replacement for the `random` module's functions. However, it may not be available on all systems, and using `secrets` directly is the preferred, more explicit approach.
37+
38+
+++
39+
40+
- **Review third-party dependencies:** Ensure that any third-party libraries you use are not relying on the `random` module for security-critical operations. Vulnerabilities can be introduced through transitive dependencies.
41+
42+
43+
## Example
44+
45+
Consider the following problematic code that uses `random` to generate a browser cookie:
46+
47+
```python
48+
"""Problematic code using random module"""
49+
import random
50+
51+
browser_cookie = random.randint(min_value, max_value)
52+
```
53+
54+
55+
This code is vulnerable because an attacker could predict the cookie value if they observe enough outputs from the same PRNG instance.
56+
57+
To improve this code, use the `secrets` module:
58+
59+
60+
Use the `SystemRandom` class. This class uses the system function `os.urandom()` to generate random numbers from sources provided by the operating system.
61+
62+
```python
63+
from random import SystemRandom
64+
safe_random = SystemRandom()
65+
66+
browser_cookie = safe_random.randint(min_value, max_value)
67+
```
68+
69+
Alternatively, if you need a drop-in replacement for `random` functions, use `SystemRandom`:
70+
71+
```python
72+
from random import SystemRandom
73+
safe_random = SystemRandom()
74+
75+
browser_cookie = safe_random.randint(min_value, max_value)
76+
```
77+
78+
However, note that `secrets` is the recommended approach for all new code requiring cryptographic randomness.
79+
80+
81+
## Discussion
82+
83+
The root cause of the security issue lies in the design goals of the Mersenne Twister algorithm. It was developed for speed and statistical quality in simulations, not for unpredictability. Its state can be fully recovered from just 624 consecutive outputs, making it trivial for an attacker to predict future values once they have observed enough random numbers.
84+
85+
The Python standard library provides the `secrets` module specifically to address this gap. Introduced in Python 3.6 via [PEP 506](https://peps.python.org/pep-0506/), `secrets` was designed to be the "go-to" module for all cryptographic randomness needs. It abstracts away platform-specific CSPRNG implementations and provides a simple, safe API for developers.
86+
87+
A common misconception is that using `random.seed()` with a high-entropy seed makes the `random` module secure. This is false—while it may make prediction more difficult initially, the Mersenne Twister's state can still be recovered from its outputs, regardless of the seed's quality.
88+
89+
## More Information
90+
91+
* https://docs.python.org/3/library/random.html
92+
* https://docs.python.org/3/library/secrets.html#module-secrets
93+
* [ CWE-330: Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html)
94+
* [CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)](https://cwe.mitre.org/data/definitions/338.html)
95+
* [CVE-2022-23472](https://nvd.nist.gov/vuln/detail/CVE-2022-23472)
96+
* [PEP 506 – Adding A Secrets Module To The Standard Library](https://peps.python.org/pep-0506/)
97+
* https://www.codiga.io/blog/python-avoid-random/
98+

‎constructs/shelve.md‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Shelve Module
2+
3+
The `shelve` module offers a simple, persistent, dictionary-like interface for storing and retrieving Python objects to and from disk. While convenient for basic local persistence, it is built directly on top of the `pickle` module and inherits all of its serious security risks.
4+
5+
## Security Concerns
6+
7+
The `shelve` module uses `pickle` for both serialization (`shelve.sync()`, object storage) and deserialization (`shelve.open()` and item retrieval). This means that loading data from a shelf file can trigger arbitrary code execution if the file originates from an untrusted source.
8+
9+
Key risks include:
10+
11+
- **Arbitrary code execution**: Malicious shelf files can exploit `pickle`'s powerful reconstruction capabilities (via `__reduce__`, custom classes, etc.) to run arbitrary Python code during unpickling.
12+
- **No built-in authentication or validation**: `shelve` performs no integrity checks or sandboxing by default.
13+
- **File-based attack surface**: Any process with write access to the shelf file (or the ability to supply a malicious `.db` file) can compromise the application that opens it.
14+
- **Silent failures and hidden dangers**: The convenience of the dict-like API can lead developers to treat shelf data as trusted without proper validation.
15+
16+
17+
## Preventive Measures
18+
19+
* **Never load untrusted shelves**: Avoid using `shelve.open()` on files received from users, networks, downloads, or any untrusted location.
20+
21+
* **Prefer safer alternatives**:
22+
* Use `json`, `toml`, `yaml` (with safe loaders), or structured formats like Protocol Buffers / MessagePack with schema validation.
23+
* For more complex object persistence, consider ORMs with proper input sanitisation (e.g., SQLAlchemy) or secure serialization libraries.
24+
25+
* **Validate and sanitise data**: Even when using `shelve` for trusted data, implement strict schema validation after loading.
26+
27+
* **Use with `pickle` restrictions**: If you must use `shelve`, restrict the `pickle` protocol to the safest level and consider custom `Unpickler` classes that limit global imports (though this is complex and not foolproof).
28+
* **File permissions and isolation**: Store shelf files with strict permissions and run the application with the principle of least privilege.
29+
30+
* **Consider `dbm` directly**: For simple key-value storage of bytes/strings, use the lower-level `dbm` modules instead of `shelve`.
31+
32+
## Example
33+
34+
**Safe usage (trusted local data only)**:
35+
36+
```python
37+
import shelve
38+
39+
with shelve.open('local_config.db') as db:
40+
db['user_settings'] = {'theme': 'dark', 'timeout': 30}
41+
settings = db['user_settings'] # Safe because file is trusted
42+
```
43+
44+
**Dangerous usage (to avoid)**:
45+
46+
```python
47+
import shelve
48+
49+
# Never do this with files from untrusted sources
50+
with shelve.open('untrusted_data.db') as db: # Arbitrary code execution possible!
51+
malicious_data = db['payload']
52+
```
53+
54+
## Discussion
55+
56+
`Shelve` is only appropriate for **fully trusted** environments — typically single-user applications where the shelf file is never exposed to external input or third parties. In practice this is near to impossible for most use cases.
57+
58+
The fundamental problem with `shelve` is that it provides an attractive, high-level interface that hides the dangerous `pickle` implementation underneath. Developers often underestimate the risk because the API feels like a simple dictionary.
59+
60+
Unlike `pickle` used directly, `shelve` adds the complication of persistent files that may be tampered with over time or replaced by attackers. This makes it especially dangerous in desktop applications, plugins, or any scenario where files can be swapped.
61+
62+
Modern Python security guidance strongly recommends avoiding `pickle`-based solutions for anything beyond fully controlled, internal use cases. The convenience of `shelve` rarely outweighs the long-term maintenance and security burden it introduces.
63+
64+
## More Information
65+
66+
* [Python Documentation: shelve — Security Considerations](https://docs.python.org/3/library/shelve.html#shelve-security)

0 commit comments

Comments
 (0)