The specifics, not the posture.
Written for engineers. Every control below is named by what it actually does at the boundary — which ranges are blocked, what happens when resolution fails, what the format cannot express.
Isolation you cannot forget to apply.
Every tenant-owned model inherits a workspace and site scoped base class, and queries always filter by tenant.
The distinction that matters: this is a scoped model base class, not a convention. A query that forgot its tenant filter is not a bug waiting to be found in review — it is a query that cannot be written, because the manager it would have to go through applies the filter itself. Foreign keys cascade, so a deletion leaves no orphan behind for a later join to find.
Scoped model base
Every tenant-owned model inherits a workspace- and site-scoped base class. The filter is structural rather than remembered.
Per-tenant vector namespaces
Each tenant gets its own Qdrant collection. A retrieval query has no way to reach another tenant's vectors, because they are not in the collection it queries.
One permission mixin
A shared permission mixin gates every endpoint, rather than each view deciding for itself and one of them being wrong.
Staff-only operator surfaces
Corpus, quality, serving and readiness APIs require staff or superuser. A tenant role cannot reach them at all.
The attacks that only exist because there is a model.
Four of these have no analogue in a conventional application, and three of them are the ones that get skipped: retrieved text treated as data rather than instruction, a fetch path that cannot be pointed at the metadata endpoint, and a weight format that cannot execute.
Prompt-injection neutralisation
Uploaded and retrieved text is sanitised before it can reach a prompt. “Ignore previous instructions” and spoofed system or assistant lines are neutralised, system and legal controls always win, and bypass attempts are logged rather than silently dropped.
Applies to retrieved corpus text as well as user uploads — a poisoned source document is the same attack as a poisoned message.SSRF guard on corpus fetching
Public HTTP and HTTPS only, and the guard is wired into the corpus fetch path itself so no adapter can go around it by calling a different client.
Fails closed on DNS resolution failure. A name that cannot be resolved is refused rather than retried against whatever the resolver returns next.Fail-safe JSON handling
Model output is validated and repaired with bounded retries. Output that cannot be repaired fails safe and is never executed — there is no path where malformed model output becomes an action.
Bounded retries, so a model that keeps producing garbage costs a fixed amount rather than an open-ended one.JSON-only model store
The model store is JSON only — no pickle, and no OSS model format. Loading a model cannot execute code, because the format has no way to carry any.
Each save is content-addressed, with the version being the hash of the weights and an active pointer per role enabling promote and instant rollback.Model-internals leakage guard
The public evidence centre and the SEO generator both run a leakage guard proving no weights, prompts or secrets escape through a public surface.
The training package is never imported by the serving path, so the request path cannot pull in training code at all.
What the fetch guard refuses
Fails closed on DNS failure- localhostand every name that resolves to it
- loopback127.0.0.0/8 and ::1
- link-local169.254.0.0/16 and fe80::/10
- reserved rangesprivate and special-purpose allocations
- cloud metadatathe instance metadata endpoints
Public HTTP and HTTPS only, enforced in the corpus fetch path rather than in each adapter — so adding an adapter cannot add a bypass.
Integrity you can verify after the fact.
Ledger entries are hash-chained per tenant, and a command validates the whole chain.
Audit logging on every high-risk action
Actor, tenant, event type and pinned versions. Refusals are logged separately with their reason, which turns refusal rate into a metric rather than an anecdote.
HMAC-signed export manifests
Audit-proof manifests are signed. An unsigned or altered manifest does not verify, and the export HMAC secret is a required production setting.
Hash-chained ledgers
Ledger entries are hash-chained per tenant, and a CLI command validates the whole chain. Tampering with one entry invalidates everything after it.
Content-hashed audit proofs
A SHA-256 is recorded at generation time; verification re-reads the stored PDF and compares in constant time.
Signed, expiring download URLs
Document downloads are issued as signed links with a token rather than as guessable paths, for invoices, credit notes and commerce exports alike.
Rate limiting and cost bounds
Throttling on AI generation and question endpoints, with a configurable free-question limit and an answer cache TTL. Abuse costs the attacker time rather than costing you money.
Upload handling
ClamAV scanning with a fail-closed option, maximum upload bytes, maximum image dimension, OCR timeouts, and EXIF stripping so an image cannot carry metadata into the system.
- calculate
- grounded answer
- corpus promote
- corpus rollback
- prompt change
- model route change
- case finalize
- case reopen
- gate waiver
- deletion
- document download
- audit proof generation
- ledger resync
- anomaly resolution
- page proposal deployment
- bookkeeper chat
- privacy export
Tell us, and we will tell you what happened.
Report anything you find to security@taxorch.com. Include what you did, what you expected and what happened instead. If it is sensitive, say so and we will arrange an encrypted channel before you send details.
We will not pursue or support legal action against research conducted in good faith under the terms below, and we will credit you in the fix notes unless you would rather we did not.
What we commit to
- Acknowledgement within two business days.
- An initial assessment, with a severity and a plan, within five business days.
- Progress updates at least every ten business days until it is closed.
- A named fix, and confirmation when it has shipped.
What we ask
- Give us reasonable time to fix it before publishing.
- Do not access, modify or delete data that is not yours — a proof of concept, not an exfiltration.
- No denial of service, spam or social engineering of our people or our customers.
- Test against your own deployment or account wherever that is possible.
There is no paid bounty programme. Saying so is better than implying one and disappointing someone who has just done us a favour.
The questions a review board asks, answered in public.
Tenant isolation, the audit trail, the training opt-out and what happens to your data if you leave. Where something is not certified or not published, the page says so rather than implying otherwise.
TaxOrch provides decision support, not professional tax advice. Exact results apply only within declared coverage. TaxOrch does not file returns or execute payments. Review all outputs before filing.