Skip to content

Security: writerslogic/facet

SECURITY.md

Security Policy

Supported Versions

Facet is pre-1.0 and under active development. Security fixes are applied to main; there is no long-term support branch yet.

Version Supported
main
< 0.3

What this policy covers

This is the policy for Facet the software, maintained in this repository. It is not the policy of any particular deployment. If you found an issue in someone's running Facet instance (a misconfiguration, an exposed admin token, exposed data), report it to that instance's operator — a deployment publishes its own operator's contact at /.well-known/security.txt, which Facet serves only from a contact that operator explicitly configured. Report it here as well if the underlying cause is a bug in Facet itself.

Reporting a Vulnerability

Please do not report security vulnerabilities through public GitHub issues.

Preferred Method

Open a private advisory via GitHub Security Advisories, or email admin@writerslogic.com.

Please include:

  • A description of the vulnerability and its impact
  • Steps to reproduce (do not include real API keys, admin tokens, or .dev.vars)
  • The affected surface (Worker/API, dashboard, client, or CLI) and version/commit

You can expect an initial response within a few days. Coordinated disclosure is appreciated; please give us a reasonable window to ship a fix before publishing details.

Scope & privacy model

Facet is privacy-first by design: unique visitors are counted with a daily-rotating, salted SHA-256 hash, and raw IP addresses are never stored, logged, or returned. Reports that are especially valuable include:

  • Any path by which a raw IP, user-agent, or other PII could be persisted, logged, or exfiltrated
  • Any way to recover cross-day visitor identity from stored data (the model guarantees this is cryptographically prevented)
  • Authentication bypasses on the admin (ADMIN_TOKEN) or API-key (clk_...) surfaces
  • Cross-site data access (a key or token reading another site's data)
  • Injection (SQL/JSON) via the collect, event, stats, or admin endpoints

Handling of secrets

Worker secrets: ADMIN_TOKEN (admin auth) is required; CF_API_TOKEN (Analytics Engine reads — the AE mirror writes through its binding and needs no token), WEBHOOK_SECRET (anomaly-webhook HMAC), FACET_SIGNING_JWK (attestation/provenance signing key), and SCITT_TOKEN (external transparency service) are optional and only used when their features are enabled. API keys are stored only as SHA-256 hashes; plaintext keys are shown once at issuance and are never retrievable. FACET_SIGNING_JWK holds a private key — its public half is published at /.well-known/jwks.json, but the private JWK must live only as a Worker secret. Never commit .dev.vars, tokens, private keys, or database ids in a report or PR.

Supply-chain provenance

The public npm packages (@writerslogic/facet, @writerslogic/facet-cli) are published from a tag-triggered GitHub Actions workflow (.github/workflows/release.yml) with two independent provenance signals, both signed via the workflow's OIDC identity through Sigstore (recorded in the public Rekor transparency log):

  • npm provenance (npm publish --provenance) — links each published version to the exact source commit and build workflow. Visible on the npm package page and verifiable with npm audit signatures.
  • GitHub build-provenance attestations (actions/attest-build-provenance) over the packed tarballs — verifiable with gh attestation verify <tarball> --repo writerslogic/facet.
  • Attested SPDX SBOM (actions/attest-sbom) — a Software Bill of Materials for each release, signed against the same tarballs and uploaded as a build artifact.

All GitHub Actions are pinned to full commit SHAs, and CodeQL, OpenSSF Scorecard, and Dependency Review run in CI.

SLSA level: this reaches SLSA v1.0 Build Level 2 — provenance is generated by a hosted build platform (GitHub-hosted runners) and is signed/non-forgeable, but the build is not yet run on a hardened, isolated reusable workflow. Reaching Build Level 3 would require moving the publish job into an isolated reusable workflow with provenance generated outside the job's control; that is a planned hardening step, not a current guarantee.

There aren't any published security advisories