Vulnerability management
Scanning, dependency monitoring, patch windows, security testing and responsible disclosure.
Continuous, against a deliberately small surface
- Automated dependency scanning runs against the repository: vulnerability alerts and security-update pull requests are enabled on it, and a weekly grouped pull request refreshes the rest, so a vulnerable package arrives as a pull request rather than an email that goes unread.
- Every install is pinned by a lockfile, so builds are reproducible and a compromised upstream release cannot enter on the next install.
- The dependency surface is small by design. The API is built on a minimal edge framework and the platform's own primitives. The marketing site has no build-time JavaScript dependencies and is generated by a script in the repository.
- No third-party JavaScript executes on our pages beyond Cloudflare's own analytics and challenge scripts, both enumerated in a restrictive Content-Security-Policy.
- The runtime is patched by the platform. There is no operating system, container image or interpreter for us to leave unpatched.
By severity, timed from when we become aware
| Severity | Definition | Remediated within |
|---|---|---|
| Critical (CVSS 9.0–10.0) | Remotely exploitable without authentication, in a component we reach | 24 hours, as emergency maintenance if required |
| High (7.0–8.9) | Serious and exploitable in our configuration | 7 days |
| Medium (4.0–6.9) | Exploitable given preconditions we partly meet | 30 days |
| Low (0.1–3.9) | Limited impact, or not reachable in our configuration | 90 days, or accepted with a written rationale and a date |
Where a finding is not exploitable in our configuration, the assessment is documented rather than the rating being reduced silently.
What runs before every deployment
- 2,834 automated tests and static type checking run on every push, and the pipeline that runs them is the deployment path: the deploy job exists only on a run in which the scan, the type check, the four test suites and the builds have passed.
- Security-relevant behaviour has its own tests. The licence filter, the authentication gate, the rate limiter, the key-digest comparison and the alerting logic each have tests asserting that they refuse, not only that they permit.
- The database's posture is measured rather than assumed. Row-level
security on 92 of 92 tables and the public role's
0 executable functions are queried from the running
database on every request to
/api/v1/facts. - Automated integrity checks run continuously in production and detect the class of failure a scanner cannot: a filter that has stopped filtering, a cursor reporting progress it did not make, a column empty on every row so a security condition matches nothing.
- Every push is scanned for credential patterns before anything else in the pipeline runs.
An independent penetration test is to be commissioned before the first enterprise agreement, and the report will be available under NDA once complete. Internal security review is continuous and has produced findings, one of which is described below.
September 2026: database function permissions
Internal review found that a set of database functions were executable by the platform's public role. Reaching them still required a credential that has only ever existed in server-side secrets, and no data was exposed, but the permission was wider than intended and the review treated it as a defect rather than an accepted risk.
Resolution. Every database call was routed through a secret-gated function running inside the database environment with a fixed operation allowlist. That was deployed and every affected endpoint verified. Execute permission was then revoked from the public role on all functions, and default privileges were changed so that a newly created function cannot arrive publicly executable. Measured afterwards: the public role can execute none of the 77 functions, and the database returns a permission error on any attempt.
The same work surfaced an unrelated defect — an endpoint that had been returning an empty result rather than an error when a call failed — which was also fixed.
Since then the design has moved on: on 9 September 2026 the secret-gated
function was retired and the database is reached through two pooled
connections, one of which cannot bypass row-level security (see
architecture). The public role's execute
set is now measured on every request and published at
/api/v1/facts: 0 of 201 functions on
11 October 2026.
We publish findings of this kind because a reviewer is entitled to see how we handle one.
How to report, and what you receive
Report to security@vaethra.com with enough detail to reproduce.
| Stage | Commitment |
|---|---|
| Acknowledgement | 2 business days |
| Initial assessment and severity | 5 business days |
| Progress updates | Every 7 days until closed |
| Fix | Per the patch windows above |
| Credit | In the changelog if you want it |
What we ask
- Do not run automated scans against the API without arranging it first. Scanner traffic is indistinguishable from abuse and will be rate-limited and logged as such. Write to us and we will agree a window.
- Do not access, modify or destroy data that is not yours, and do not degrade the service for others.
- Allow reasonable time to fix before publishing. We will not ask for indefinite silence, and we will not take legal action against anyone reporting in good faith under these terms.
We do not currently run a paid bug bounty. Reports are acknowledged, fixed and credited.
Our contact details are also published at /.well-known/security.txt in the format defined by RFC 9116.