Who can send and who can read
- Every member of the workspace, at every role, can read, download, wait, inject, and delete. There is no read-only role for testing data.
- API keys have no scopes. A key that can list monitors can also read every captured request and email in its workspace. Create a separate key for CI so you can revoke it alone. See API keys.
- The URL and the domain are not credentials for reading. An inbox or domain in another workspace returns
404.
The inbox URL is a write secret
The ingest URL ishttps://api.devhelm.io/api/v1/ingest/<public-token>. The token is 256 random bits, and ingest takes no other authentication. An unknown token and a disabled inbox both return 404.
The token cannot be rotated. If a URL leaks:
- Create a new inbox and point your sender at its
httpUrl. - Delete the old inbox. Its URL returns
404right away.
status to disabled. Senders get 404 until you enable it again.
Testing addresses are not secrets. Every local part on a domain is an inbox, and anyone who knows or guesses an address can send mail to it. Assert on the sender or subject when a stray message would break a test.
Captured headers are stored as sent
DevHelm stores every request header and every email header without redaction, along with the raw body, the query string, andsourceIp. An Authorization, Cookie, X-Api-Key, or signature header a sender includes is returned to anyone who can read the workspace. Webhook header names are stored lowercased; email header names keep their case.
Point senders at an inbox with test credentials only. When a test captures a credential by design, delete the event when the test ends:
inboxes events clear removes every event on the inbox.
Returned HTML is not sanitized
GET on an email message returns html exactly as received, and a webhook body is returned as sent. Scripts, forms, remote images, and meta refreshes are left in place. Render captured HTML only inside a sandboxed frame:
sandbox attribute blocks scripts, forms, popups, and same-origin access. Never insert captured HTML with innerHTML.
API keys in CI
- Store the key as an encrypted secret named
DEVHELM_API_TOKEN, and the workspace ID asDEVHELM_WORKSPACE_ID. Expose them only to the job that runs the tests. - GitHub does not pass repository secrets to
pull_requestruns from forks, or to runs started by Dependabot. Skip the DevHelm tests on those runs instead of failing them. - Do not use
pull_request_targetto get secrets into a fork’s run. Checking out the fork’s code there lets that code read the key. - If a key leaks, revoke it under API keys and create a new one.
Retention and cleanup
An inbox’sretentionDays defaults to your testing plan’s ceiling, and a higher value returns 403 INBOUND_RETENTION_ABOVE_PLAN. The setting is stored, but DevHelm does not currently delete captured data on a schedule. Events and messages stay until you delete them, so clean up in test teardown.
maxEvents (default 10000) caps how many events an inbox keeps; the oldest is dropped as a new one arrives. Set it low on inboxes that capture sensitive payloads.
Do not delete the assigned email domain to clean up. Concurrent runs share it, and the next address() call creates a domain with a new name, which breaks stored addresses.
Do not use testing addresses for real accounts
A testing address receives any mail sent to it, and every member of the workspace can read it. A password reset or login link sent there can be used by anyone who reads it.- Do not register real accounts, on your product or a third party’s, with a testing address.
- Do not send customer or personal data to an inbox or a testing address. Use synthetic users and fixtures.
- Do not point a production webhook sender at an inbox. Use a staging sender with test credentials.
Next steps
Limits, quotas, and errors
Plan quotas, size limits, and every error code.
Testing in CI
Secrets, per-job inboxes, and teardown in GitHub Actions.
Webhook inboxes
How inboxes capture and store requests.
Email testing
How testing mailboxes receive and store mail.