(security)=
# {fas}`lock` Security

## Pickle Vulnerabilities
:::{warning}
The python `pickle` module has [known security vulnerabilities](https://docs.python.org/3/library/pickle.html),
potentially leading to code execution when deserialzing data.
:::

This means it should only be used to deserialize data that you trust hasn't been tampered with.
Since this isn't always possible, requests-cache can optionally use
[itsdangerous](https://itsdangerous.palletsprojects.com) to add a layer of security around these operations.
It works by signing serialized data with a secret key that you control. Then, if the data is tampered
with, the signature check fails and raises an error.

Optional dependencies can be installed with:
```bash
pip install requests-cache[security]
```

## Creating and Storing a Secret Key
To enable this behavior, first create a secret key, which can be any `str` or `bytes` object.

One common pattern for handling this is to store it wherever you store the rest of your credentials
([Linux keyring](https://itsfoss.com/ubuntu-keyring),
[macOS keychain](https://support.apple.com/guide/mac-help/use-keychains-to-store-passwords-mchlf375f392/mac),
[password database](https://keepassxc.org), etc.),
set it in an environment variable, and then read it in your application:
```python
>>> import os
>>> secret_key = os.environ['SECRET_KEY']
```

Alternatively, you can use the [keyring](https://keyring.readthedocs.io) package to read the key
directly:
```python
>>> import keyring
>>> secret_key = keyring.get_password('requests-cache-example', 'secret_key')
```

## Signing Cached Responses
Once you have your key, create a {py:func}`.safe_pickle_serializer` with it:
```python
>>> from requests_cache import CachedSession, safe_pickle_serializer
>>> serializer = safe_pickle_serializer(secret_key=secret_key)
>>> session = CachedSession(serializer=serializer)
>>> session.get('https://httpbin.org/get')
```

:::{note}
You can also make your own {ref}`custom-serializers`, if you would like more control over how
responses are serialized.
:::

You can verify that it's working by modifying the cached item (*without* your key):
```python
>>> serializer_2 = safe_pickle_serializer(secret_key='a different key')
>>> session_2 = CachedSession(serializer=serializer_2)
>>> cache_key = list(session_2.cache.responses.keys())[0]
>>> session_2.cache.responses[cache_key] = 'exploit!'
```

Then, if you try to get that cached response again (*with* your key), you will get an error:
```python
>>> session.get('https://httpbin.org/get')
BadSignature: Signature b'iFNmzdUOSw5vqrR9Cb_wfI1EoZ8' does not match
```

(default-filter-params)=
## Removing Sensitive Info
The {ref}`ignored_parameters <filter-params>` option can be used to prevent credentials and other
sensitive info from being saved to the cache. It applies to request parameters, body, and headers.

Some are ignored by default, including:
* `Authorization` header (most authentication systems)
* `access_token` request param (used by OAuth)
* `access_token` in POST body (used by OAuth)
* `X-API-KEY` header (used by OpenAPI spec)
* `api_key` request param (used by OpenAPI spec)
