Skip to content
Apothem
Security

Security

Apothem security posture — OpenSSF Scorecard target, vulnerability reporting, hardening surfaces.

Apothem's security posture is built on five pillars: supply-chain hardening, vulnerability response, branch protection, release signing, and continuous security analysis. This section documents each surface.

Threat model

Apothem is a configuration materializer. It reads a shared profile and writes harness-native configuration files into the directories each harness reads. That single function bounds what it trusts and what it does not.

  • What Apothem trusts. The shared profile you author and the bundled source tree placed by the installer. The profile is your declared intent; the engine treats it as authoritative input after schema validation.
  • What Apothem does not trust. Profile contents reach the filesystem only after validation: schema failures, unknown harness IDs, unsafe project paths, missing manifest sources, target traversal, and symlink crossings all stop before any write and return structured diagnostics with files_written: [].
  • What materialized output never carries. No secrets. Profile diagnostics redact secret-like keys and token-shaped values before they reach plain output, JSON, logs, docs snippets, or tests, and public examples use fake placeholder identities and domains. Materialized configuration is meant to be committed and shared; it carries no credentials.
  • The universal-deny floor. The Claude Code settings.json that Apothem materializes carries a non-negotiable deny floor regardless of any per-harness allow-list; on other harnesses the same floor is policy text in the materialized rules, not a settings-level deny list — secrets paths (.env*, ~/.ssh/**, credential stores), destructive shell operations (rm -rf, sudo, force-pushes to protected branches), and execution of untrusted input. No allow-list silently widens this floor.
  • Blast radius. Writes are scoped to the harness directories and the Apothem-owned support subtrees. Existing managed targets are backed up before replacement and shared discovery directories are merged child-by-child, so unrelated operator-authored files remain in place.

Runtime safety posture

Harness lifecycle and profile-write commands validate before writing. Profile schema failures, unknown harness IDs, unsafe project paths, missing manifest sources, target traversal, and symlink crossings stop before filesystem writes and return structured diagnostics with files_written: [].

Install and update operations preserve existing managed targets by backing them up before replacement. Shared discovery directories are merged child-by-child so unrelated operator-authored files remain in place. --dry-run performs the same validation and reports planned outcomes without creating directories or files.

Profile diagnostics redact secret-like keys and token-shaped values before they reach plain output, JSON output, logs, docs snippets, or tests. Public examples use fake placeholder identities and domains.

Reporting a vulnerability

Use Private Vulnerability Reporting on the repository's Security tab. The full policy, supported-version matrix, and response timelines are at SECURITY.md.

Supply-chain release evidence

Every release artifact ships with:

  • SLSA-3 build provenance via slsa-framework/slsa-github-generator
  • Sigstore signatures via sigstore/cosign-installer
  • CycloneDX SBOM of the shipped wheel and sdist, written by scripts/release/generate_sbom.py: the apothem package, every package vendored under apothem/_vendor with its license, the declared runtime requirements, and each distribution's SHA-256. The SBOM is signed and covered by the build provenance like the distributions
  • npm provenance statements via Trusted Publishing OIDC on @ahmed-g-gad/apothem
  • GPG-signed git tags (EDDSA key 70396FED9C634163)

Verify a release

Download every asset of a release into an empty directory, then check the signatures and the build provenance. Replace vX.Y.Z and X.Y.Z with the release you downloaded.

gh release download vX.Y.Z --repo ahmed-g-gad/apothem
cosign verify-blob \
  --bundle apothem-X.Y.Z-py3-none-any.whl.cosign.bundle \
  --certificate-identity https://github.com/Ahmed-G-Gad/apothem/.github/workflows/release.yml@refs/tags/vX.Y.Z \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  apothem-X.Y.Z-py3-none-any.whl
slsa-verifier verify-artifact \
  --provenance-path provenance.intoto.jsonl \
  --source-uri github.com/Ahmed-G-Gad/apothem \
  --source-tag vX.Y.Z \
  apothem-X.Y.Z-py3-none-any.whl apothem-X.Y.Z.tar.gz

cosign prints Verified OK and slsa-verifier prints PASSED: SLSA verification passed. Repeat the cosign command for any other asset with its <asset>.cosign.bundle (earlier releases name the platform-archive and SHA256SUMS bundles <asset>.sig). The darwin and linux archives are the same bytes under two names, so SHA256SUMS lists one digest twice. From a clone, bash scripts/release/verify-provenance.sh <download-dir> runs all three checks, the SHA256SUMS manifest included, in one pass.

Two details decide whether verification means anything:

  • Owner casing. Identity checks are case-sensitive, and the certificates carry the owner as GitHub reports it: Ahmed-G-Gad. A lowercase owner fails both tools.

  • Exact identity. Prefer --certificate-identity with the full subject above. To accept any release tag, anchor the pattern at both ends:

    --certificate-identity-regexp '^https://github\.com/Ahmed-G-Gad/apothem/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$'

    An unanchored pattern such as github.com/Ahmed-G-Gad/apothem also matches a forged subject that only contains that text, for example a workflow in another repository on a branch named after this one.

The release-cycle runbook records the same commands as the maintainer's post-release check.

Rebuild a release and compare

The wheel and sdist are reproducible: rebuilding the tag with the release toolchain gives the published SHA-256 digests. Use Python 3.12 on Linux, as the release does:

git clone https://github.com/ahmed-g-gad/apothem && cd apothem
git checkout vX.Y.Z
python3.12 -m venv .build && . .build/bin/activate
pip install --require-hashes -r scripts/release/requirements-build-linux.txt
export SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)"
python -m build --no-isolation
python scripts/release/normalize_sdist.py dist/*.tar.gz
sha256sum dist/*

Compare the digests with the published wheel and sdist. The build uses the hash-locked setuptools that pyproject.toml pins, and normalize_sdist.py removes the build time, file owners and checkout timestamps from the sdist.

On this page