SOFApy
A Python client library for the MacAdmins SOFA (Simple Organized Feed for Apple) API.
Query Apple macOS software update information, security releases, and CVE data with both synchronous and asynchronous clients.
Installation
Using uv (recommended):
uv add sofapy
Using pip:
pip install sofapy
Quick Start
Synchronous Client
from sofapy import SofaClient
client = SofaClient()
# Get the full SOFA feed
feed = client.get_feed()
print(f"Feed updated: {feed.update_hash}")
# Get CVEs affecting a specific macOS version
cves = client.get_cves("15.1.0")
print(f"Total CVEs: {cves.total_count}")
print(f"Actively exploited: {cves.exploited_count}")
# Only get actively exploited CVEs
exploited = client.get_cves("15.1.0", exploited_only=True)
for cve in exploited.actively_exploited_cves:
print(f" ⚠️ {cve}")
# Check how current a version is
currency = client.get_currency_info("15.0.0")
print(f"Score: {currency.currency_score}/100")
print(f"Recommendation: {currency.recommendation}")
# Get latest versions for all OS families
latest = client.get_latest()
for name, info in latest.items():
print(f"{name}: {info.latest_version}")
# Filter to specific OS family
sequoia = client.get_latest(os_filter="Sequoia")
Asynchronous Client
import asyncio
from sofapy import AsyncSofaClient
async def main():
client = AsyncSofaClient()
# Same API, just await the calls
feed = await client.get_feed()
cves = await client.get_cves("15.1.0", exploited_only=True)
currency = await client.get_currency_info("15.0.0")
latest = await client.get_latest()
print(f"Latest Sequoia: {latest.get('Sequoia 15').latest_version}")
asyncio.run(main())
Raw JSON Access
from sofapy import SofaClient
client = SofaClient()
# Get raw JSON dict instead of parsed models
raw_feed = client.get_feed(raw=True)
print(raw_feed["UpdateHash"])
Command Line Interface
sofapy includes a CLI for quick queries:
# Show latest versions for all macOS releases
sofapy latest
# Filter to specific OS family
sofapy latest --os Sequoia
# Output as JSON
sofapy latest --json
# Get CVEs affecting a version
sofapy cves 15.1.0
# Only show actively exploited CVEs
sofapy cves 15.1.0 --exploited-only
# Check version currency
sofapy currency 15.0.0
# Get the full feed (parsed)
sofapy feed
# Get raw JSON feed
sofapy feed --raw
# Enable debug logging
sofapy --debug latest
# Show help
sofapy --help
Models
sofapy returns strongly-typed Pydantic models:
| Model | Description |
|---|---|
SOFAFeed |
Complete feed with all OS versions |
OSVersionInfo |
Info for a specific OS family |
SecurityRelease |
Individual security release details |
CVEResult |
Result from get_cves() |
CurrencyInfo |
Result from get_currency_info() |
LatestInfo |
Result from get_latest() |
Helpful Properties
# CVEResult
cves.has_exploited_cves # bool - any actively exploited?
cves.is_vulnerable # bool - any CVEs at all?
# CurrencyInfo
currency.needs_update # bool - not on latest?
currency.is_critical # bool - 3+ security updates missed?
# LatestInfo
latest.has_exploited_cves # bool - any actively exploited?
Contributing
Contributions are welcome! If you find a bug or have a feature request, please open an issue on GitHub.
To contribute code:
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
uv run pytest - Submit a pull request
Acknowledgments
This library is a wrapper for the excellent SOFA project by MacAdmins.
- SOFA Website: https://sofa.macadmins.io
- SOFA Documentation: https://sofa.macadmins.io/docs
- SOFA GitHub: https://github.com/macadmins/sofa
SOFA provides comprehensive, up-to-date information about macOS security releases and CVEs. All data served by sofapy comes from the official SOFA feed.
License
Apache 2.0 License - see LICENSE for details.
Metadata
Release files for sofapy 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sofapy-0.1.1.tar.gz | 33.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sofapy-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.2 kB
Release files / sofapy-0.1.1.tar.gz
| Download URL | sofapy-0.1.1.tar.gz |
|---|---|
| Size | 33.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d55ae759b16982f627cda802d9e967f910f22f9c038f7c20a3a15b81ee4757cd
|
|
BLAKE2b-256 checksum How to use checksums |
5354445f56442af95b78a5309f0788bef2e387fb4073167e38ede50d9421504c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 13, 2025.
Transparency logRelease files / sofapy-0.1.1-py3-none-any.whl
| Download URL | sofapy-0.1.1-py3-none-any.whl |
|---|---|
| Size | 23.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0e6171bfadf3f1dceca964160128607bf30877a97da42e85e84601a9474712b9
|
|
BLAKE2b-256 checksum How to use checksums |
79cfd13b05d1350dd07028e635c4aa7bb55ac4d8a3dbcfec5417c38f91dde514
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 13, 2025.
Transparency log