Security policy
Reporting a vulnerability
Section titled “Reporting a vulnerability”Please report security issues privately rather than opening a public issue.
Email security@wayscribe.dev, or open a confidential issue with the Confidential box ticked. Email reaches only the maintainer; a confidential issue is visible only to project members.
Include what you did, what happened, and what you expected. A proof of concept helps but is not required.
This is a small project without a dedicated security team. Expect an acknowledgement within a week. Please give a reasonable window for a fix before disclosing publicly.
Wayscribe is self-hosted. There is no hosted service, so there is no production environment to test against. Please test against your own installation.
In scope:
- the API (
apps/api), the web interface (apps/web), and the Node SDK - the
@wayscribe/nodepackage and the container images, once published (nothing is published yet, and releases will be 0.x) - the default Compose configuration
Out of scope, because they are known and documented rather than undiscovered:
- The development defaults are published.
ENCRYPTION_KEYandADMIN_TOKENship with values committed to this repository so the demo runs with nothing configured. The API warns at every boot while they are in use. Running a real installation on them is a misconfiguration, not a vulnerability. - The admin token is a single shared secret. There are no user accounts, no per-user permissions, and no record of who used it. It can read every recorded payload of every project on the installation. See ADR-029.
- Propagated journey context is not authenticated. A caller who can set headers on a request to an instrumented service, and who knows a valid journey ID, can attach events to that journey. Extraction validates shape only, which stops injection and garbage but not a well-formed forgery. This is stated in the Phase 4 design and is not an authorization control.
- Anything requiring an attacker to already hold the admin token or a valid API key, unless it crosses a project boundary. Cross-project isolation is structural (composite foreign keys), and a break there is in scope.
Verifying the images you run
Section titled “Verifying the images you run”Nothing is published yet. When a release is, its images at
registry.gitlab.com/jojithedev/wayscribe/api and /web are signed with
Sigstore keyless signing by this project’s GitLab release pipeline, and each
platform’s image carries a signed CycloneDX software bill of materials. The
signing certificate names the pipeline and the release tag, so a check like this
one proves the image came from a tagged release of this repository. Replace
vX.Y.Z with the release you run; releases will be 0.x, such as v0.1.0:
cosign verify registry.gitlab.com/jojithedev/wayscribe/api:vX.Y.Z \ --certificate-identity 'https://gitlab.com/jojithedev/wayscribe//.gitlab-ci.yml@refs/tags/vX.Y.Z' \ --certificate-oidc-issuer https://gitlab.comExtracting and checking the SBOM is described in docs/OPERATIONS.md §11. An image offered as Wayscribe that fails this check, or a signature from any other identity, is in scope: report it as above.
That claim rests on who can create a v* tag, because the certificate names the
tag and nothing else about who pushed it. The v* tags must be protected in
GitLab, creatable by Maintainers only, and this must be in place before the
first release; until it is, anyone with Developer access could create a tag
whose pipeline signs an image this check accepts. The release pipeline also
runs only for tags of the exact form vMAJOR.MINOR.PATCH, so the repository’s
phase-* and usable-v0 tags and pre-release tags never publish, but that is a
guard against mistakes rather than a control.
What the product does with your data
Section titled “What the product does with your data”Nothing captured is sent anywhere you did not configure: the only outbound
requests the API makes are replays, to destinations an admin registered on a
host REPLAY_ALLOWED_HOSTS lists. The running services send no telemetry and
no analytics, and make no outbound connection other than the ones your own
configuration creates. Building the images is not offline: it downloads base
images, Alpine packages and npm packages. Next.js’s build telemetry is
switched off (NEXT_TELEMETRY_DISABLED=1) in the web image and in the web
package’s scripts.
Entity identifiers and alias values are encrypted at rest with keys derived from
ENCRYPTION_KEY. Payloads are not: they are stored as jsonb, which is
exactly why redaction matters: payloads are redacted in your process before they
leave it, and again on the server before they are written, against a built-in
list of secret names matched at any depth.
Wayscribe records the contents of your integration payloads. Treat the
database as holding whatever your workflows carry. If that includes regulated
data (health records, payment details, government identifiers), review
captureMode before enabling it. metadata-only records the shape of a journey
without storing payloads at all.
See docs/SECURITY.md for the threat model and docs/OPERATIONS.md for key handling.