Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ jobs:
python-version: "3.12"
- name: Build package
run: pip install build && python -m build
- name: Generate CycloneDX SBOM
run: |
pip install cyclonedx-bom
VERSION=$(cat VERSION)
python -m venv /tmp/sbom-env
/tmp/sbom-env/bin/pip install --upgrade pip
/tmp/sbom-env/bin/pip install --no-deps dist/*.whl
cyclonedx-py environment /tmp/sbom-env/bin/python \
--output-format JSON \
--output-file "dist/bitmath-${VERSION}.cdx.json"
- name: Upload dist artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand All @@ -30,6 +40,7 @@ jobs:
environment: pypi
permissions:
id-token: write
contents: write
steps:
- name: Download dist artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand All @@ -38,3 +49,13 @@ jobs:
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
# Keep the SBOM out of the PyPI upload; it ships on the GitHub release instead.
packages-dir: dist/
skip-existing: false
- name: Attach SBOM to GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${GITHUB_REF#refs/tags/}"
gh release upload "$TAG" dist/bitmath-*.cdx.json --clobber --repo "$GITHUB_REPOSITORY"
32 changes: 32 additions & 0 deletions .github/workflows/sca.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: SCA Security Scan

on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
schedule:
- cron: "0 0 * * 0"
workflow_dispatch:

permissions: read-all

jobs:
audit:
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"

- name: Audit dev dependencies with pip-audit
uses: pypa/gh-action-pip-audit@1220774d901786e6f652ae159f7b6bc8fea6d266 # v1.1.0
with:
inputs: requirements.txt
402 changes: 402 additions & 0 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Maintainers

bitmath is a one-person project, and has been since 2014. This file
exists so downstream consumers (and any future contributors) can see
exactly who has the keys to the kingdom and what those keys unlock.

## Current Maintainer

**Tim Case** (GitHub: [@timlnx](https://github.com/timlnx))

* Role: Project lead, sole maintainer
* Contact: `bitmath@lnx.cx`
* Bluesky: [@lnx.cx](https://bsky.app/profile/lnx.cx)
* Homepage: [Technitribe](https://blog.lnx.cx)
* Formerly: Tim Bielawa (`tbielawa`)

## Access to Sensitive Resources

I have admin access to the following resources. Nobody else does.

* The [timlnx/bitmath](https://github.com/timlnx/bitmath) GitHub
repository (admin role, including the ability to change branch
protection rules, manage secrets, and modify security settings).
* The `bitmath` project on [PyPI](https://pypi.org/project/bitmath/).
Publishing happens through PyPI Trusted Publishing (OIDC), so there
is no long-lived API token to leak. The trust relationship is
configured in PyPI's web UI and is scoped to the
`.github/workflows/publish.yml` workflow on the `master` branch.
PyPI account has 2fa enabled.
* The [bitmath on Read The Docs](https://bitmath.readthedocs.io/)
documentation project.
* The `bitmath@lnx.cx` email address used for private vulnerability
reports (see [SECURITY.md](SECURITY.md)).

If you ever see a release on PyPI, a tag pushed to master, or a
security advisory published that did not originate from me, treat it
as a compromise and reach out immediately through any of the contact
channels in [SECURITY.md](SECURITY.md).

## Responsibilities

As the sole maintainer I am responsible for:

* Reviewing and merging pull requests.
* Cutting releases (version bumps, `NEWS.rst` entries, tags, PyPI
publication via the OIDC workflow).
* Triaging security reports per the timelines in
[SECURITY.md](SECURITY.md).
* Enforcing the [Code of Conduct](CODE_OF_CONDUCT.md). Note that I am
both the sole enforcer and the sole maintainer, which means if a
Code of Conduct concern involves me directly, the project itself
cannot offer you a neutral venue. Your remedies in that case are
the usual ones available against any open source maintainer: public
comment on the issue tracker, a fork, or moving to a different
library. I would rather be honest about that limitation than
pretend the project has a governance structure it does not have.
* Keeping the dependency surface honest. bitmath has zero runtime
dependencies on purpose; development dependencies are listed in
`requirements.txt`.

## Decision Making

Decisions are made by me, with input solicited from the issue and PR
discussions when the question is non-obvious or has visible downstream
impact. I try to write up the reasoning when something might surprise
people (see commit messages and `NEWS.rst` for the audit trail).

## Becoming a Maintainer

bitmath has not historically had additional maintainers, but the
project has been around for over a decade and I am not immortal. If
you are interested in helping carry this forward, open an issue or
reach out by email. Co-maintainership would start with regularly
landing reviewed contributions and graduate to write access after we
have built up some trust.

### Open Maintainer Request: Debian / Ubuntu Packaging

There is a standing ask tracked in [issue
#117](https://github.com/timlnx/bitmath/issues/117) ("Deb Maintainer
Wanted") and echoed in the [contributing
guide](https://bitmath.readthedocs.io/en/latest/contributing.html#supported-python-versions):
bitmath currently tracks the Python versions shipped in the current
and previous major RHEL releases via EPEL, because that is the
ecosystem I personally pay attention to. There is no official Debian
or Ubuntu release channel right now and I am looking for somebody to
take over `.deb` patching and the related distribution coverage. This
is a real way to get involved without having to take on the entire
project. Comment on #117, email me, or open a fresh issue if you want
to claim the role.

## Inactive Maintainers

None at present.
13 changes: 10 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.. image:: https://api.securityscorecards.dev/projects/github.com/timlnx/bitmath/badge
:target: https://securityscorecards.dev/viewer/?uri=github.com/timlnx/bitmath
:alt: OSSF Scorecard
.. image:: https://www.bestpractices.dev/projects/12749/badge
:target: https://www.bestpractices.dev/en/projects/12749
:alt: OpenSSF Best Practices
.. image:: https://www.bestpractices.dev/projects/12749/baseline
:target: https://www.bestpractices.dev/projects/12749
:alt: OpenSSF Baseline

.. image:: https://github.com/timlnx/bitmath/actions/workflows/python.yml/badge.svg
:target: https://github.com/timlnx/bitmath/actions/workflows/python.yml
.. image:: https://img.shields.io/pypi/v/bitmath.svg
Expand All @@ -16,9 +26,6 @@
.. image:: https://github.com/timlnx/bitmath/actions/workflows/bandit.yml/badge.svg
:target: https://github.com/timlnx/bitmath/actions/workflows/bandit.yml
:alt: Bandit Security Scan
.. image:: https://api.securityscorecards.dev/projects/github.com/timlnx/bitmath/badge
:target: https://securityscorecards.dev/viewer/?uri=github.com/timlnx/bitmath
:alt: OSSF Scorecard
.. image:: https://img.shields.io/github/issues/timlnx/bitmath?style=flat-square
:target: https://github.com/timlnx/bitmath/issues
:alt: Open issues
Expand Down
62 changes: 61 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ As of the 2.0.0 re-factor only versions ≥ 2.0.0 will receive support. Versions
| `≥ 2.0.0` | :white_check_mark: |
| `< 2.x.y` | :x: |

### Scope of Support

* **Security fixes** are issued as patch releases on the latest minor in the 2.x series. If the current line is 2.1.x, security fixes ship as 2.1.y.
* **Bug fixes** are issued on the latest minor in the 2.x series. Older minors do not receive bug-fix backports unless the bug is also a security issue covered above.
* **Functional changes** ship in new minor releases (2.x → 2.(x+1)).

### Duration of Support

* The **2.x series** receives security fixes for as long as it is the current major. Today that is open-ended; a future 3.x release would start a deprecation clock on 2.x with at least 12 months of overlap announced in `NEWS.rst` before 2.x support ends.
* The **1.x series** (legacy) is end-of-life. No further releases will be made on 1.x. Users on 1.x should plan a migration to 2.x; the 2.x API is drop-in compatible for the documented public surface.
* The **pre-1.x series** is historical and not supported in any form.

This list will be updated when future releases are made in the 2-version series that require specific callouts for supportability.

If you have discovered what you think is a harmful bug with the potential for exploitation in a supported version series, and this bug may lead to loss of life or data, then you have two options for reporting available to you:
Expand All @@ -34,11 +46,59 @@ You may also reach out to me at this email address:

* `bitmath@lnx.cx`

Please include a tag in the subject indicating the sensitivity of the issue. I will respond and we will triage the issue, a disclosure statement will be made as soon as we understand the potential impact and have prepared a mitigation.
Please include a tag in the subject indicating the sensitivity of the issue.

## Response Timeframes

I treat security reports as the top of my queue. The commitments I make to anybody who files one:

* **Acknowledgement of receipt: within 72 hours.** This is just a "got it, working on it" reply so you know the report did not get lost. If you do not hear back in three days, the email may not have made it; try one of the backup channels below.
* **Initial triage assessment: within 7 days.** This is where I tell you whether the report is reproducible, what the rough severity looks like, and what the disclosure timeline will be.
* **Coordinated disclosure: as soon as we have a fix prepared and an impact statement we both agree on.** I aim to publish a [GitHub Security Advisory](https://github.com/timlnx/bitmath/security/advisories) and a `NEWS.rst` entry alongside the patch release that contains the fix. If the issue is severe enough that disclosure has to happen before a fix is ready, we coordinate the timing together.

These are commitments, not guarantees. bitmath is maintained by one person on the side. If I am on a plane or in a hospital the clock will keep ticking and I will catch up when I land. The backup channels below exist precisely for "I tried email and got nothing back" situations.

As an emergency backup you can find me on bsky or instagram and direct message me there:

* [bsky - @lnx.cx](https://bsky.app/profile/lnx.cx)
* [insta - @tim.lnx](https://www.instagram.com/tim.lnx/)

For less serious security issues with lower potential for exploitation or damage, please open a bug on the project and apply the `security` label to it.

## Secrets and Credentials Policy

bitmath is built around the principle that **no long-lived secrets should exist in the project**. The policy is short because the implementation is austere.

### What Secrets the Project Handles

* **PyPI publish authority** is handled via [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC). The publish workflow exchanges a short-lived GitHub Actions OIDC token for upload credentials at the moment of publication. There is no long-lived PyPI API token stored as a GitHub secret.
* **Read The Docs build credentials** are managed by Read The Docs via OAuth integration with GitHub. No credentials are stored in this repo.
* **The `bitmath@lnx.cx` email address** is a forwarding alias used only for security correspondence. Compromise of that mailbox does not affect any project resource directly.

### Storage

* No secret values are stored in the repository. GitHub secret scanning is enabled at the repository level and runs continuously.
* No secret values are stored in `.github/workflows/*.yml`. The workflows authenticate via OIDC tokens, not stored credentials.
* The list of GitHub Actions secrets configured on this repository is **empty**, verifiable with `gh api /repos/timlnx/bitmath/actions/secrets`.

### Access Control

* The single maintainer (see [MAINTAINERS.md](MAINTAINERS.md)) has admin access to the repository, the PyPI project, and the Read The Docs project.
* The PyPI Trusted Publishing trust relationship is scoped to the `.github/workflows/publish.yml` workflow on `master`. Any other workflow or branch attempting to authenticate to PyPI as bitmath will be rejected.
* Two-factor authentication is required on both the GitHub account (authenticator app + GitHub Mobile, SMS disabled) and the PyPI account.

### Rotation

* OIDC tokens are short-lived (minutes) and rotated automatically on every workflow run by GitHub Actions and PyPI.
* No long-lived credentials exist, so there is no rotation schedule to maintain.
* The Trusted Publisher trust relationship itself can be revoked or re-scoped via the PyPI web UI if the workflow file ever needs to change in a way that would alter the trust boundary.

### Incident Response

If a project secret or credential is suspected to be compromised:

1. Revoke the Trusted Publisher relationship on PyPI immediately, before doing anything else. This breaks any in-flight publish attempt by an attacker.
2. Audit recent activity in GitHub Actions runs and PyPI release history for unexpected events. The PyPI publish journal and GitHub Actions logs are public and inspectable.
3. Reach out through the reporting channels above so the incident can be coordinated and disclosed.

This policy is reviewed at every minor release.
Loading
Loading