Please report security vulnerabilities privately via email to rex@rexthetics.com with subject [uwscrape security]. Do not open a public GitHub issue.
Expected initial response: within 7 days. For high-severity issues (token forgery, state leakage between anonymous sessions, source-reference tampering that could mislead an academic decision), please mark the subject [uwscrape security URGENT].
If you have a PGP key requirement or need an encrypted channel, please mention this in your first message and one will be set up.
uwscrape is advisory only and is not affiliated with the University of Waterloo. It does not run at request time against any live Waterloo or Kuali surface; the runtime backend serves only release-gated SQLite indexes published offline. The threat model below reflects that posture.
- Authentication / authorization of anonymous state tokens (
Authorization: Bearer <state_token>). - HMAC verifier storage, key rotation, and key-leak recovery.
- Cross-session state leakage in the backend (
internal/statestore,internal/stateauth). - Information disclosure via API envelopes, logs, telemetry, error responses, or shareable view-state URLs.
- Cache-poisoning, response-injection, or smuggling against
/api/v1/*handlers. - Denial-of-service paths that bypass the documented graph-view bounds or rate-limit windows.
- Frontend XSS, CSRF, or transport-validation bypass at the Zod boundary.
- Supply-chain integrity of build inputs (
go.sum,pnpm-lock.yaml,Cargo.lock).
- The accuracy or correctness of Waterloo course/credential data itself. Source references are preserved end-to-end so users can verify against the Waterloo Kuali catalog — academic decisions remain the user's responsibility.
- Issues that require physical or network access to the operator's deployment host.
- Vulnerabilities in test fixtures or
.dev/artifacts (these are not user-facing). - Issues that require running the offline scraper with
UWSCRAPE_ALLOW_LIVE_WATERLOO=1.
- state_token is the only identity. Minimum 256 bits of randomness, base64url no padding.
- Transported only via
Authorization: Bearer. Tokens in URLs, query parameters, telemetry, logs, or test artifacts are a vulnerability. - The backend stores an HMAC verifier keyed by
UWSCRAPE_TOKEN_KEY_PATH. Raw tokens are never persisted. - Key files are 32+ random bytes; rotation is supported via versioned keys (
token_key_version). After rotation, old tokens fail closed. DELETE /api/v1/state/currentis a hard delete. Subsequent requests with the same token return401 unauthorizedindistinguishable from any unknown token. A minimal tombstone (no academic state content) is retained for audit.
- Backend startup fails closed on
release-decision.jsonstatusrejected, missing decision, unsupported schema version, or missing required files (course-universe.sqlite,build-metadata.json,validation-summary.json,build-report.md). - The runtime never opens a network connection to Waterloo or Kuali. Any code path doing so is a vulnerability.
- The state SQLite database is physically separate from the index SQLite. The runtime opens the index read-only.
- The frontend does not compute academic truth. Course unlock, credential progress, contribution, and feasibility come from backend
academic_resultpayloads only. A frontend-only computation that surfaces academic status is a vulnerability. - All API responses are validated against a Zod schema at the transport boundary before rendering.
- Shareable view state (URL params) is restricted to view mode, selected course, target credential, and selected node. The presence of
state_token, token fingerprints, grades, notes, or any other state payload in the URL is a vulnerability.
- Affected commit SHA or release tag.
- Reproduction steps or a proof-of-concept (curl, Playwright, or unit test).
- Whether the issue requires authenticated state, anonymous state, or no state.
- Observed impact and your assessment of severity.
Coordinated disclosure. By default the maintainer will:
- Acknowledge receipt within 7 days.
- Validate and triage within 14 days.
- Land a fix in a private branch and prepare a release.
- Coordinate a disclosure date with the reporter (default: 90 days from initial report, or 30 days after a fix is publicly available, whichever is sooner).
- Credit the reporter in release notes unless anonymity is requested.
These are documented architectural constraints and not in-scope vulnerability reports:
- There is no account recovery, no email recovery, no password recovery — a lost
state_tokenis unrecoverable by design (ADR 0011). - There is no audit log of academic state contents (ADR 0019).
- Hot-swap of indexes at runtime is intentionally unsupported; index replacement requires a restart (ADR 0010).
- WebGPU is optional and may be absent without affecting the app (ADR 0022).