Threat model
The prompt-injection and privacy threats the assistant is designed against, the control for each, and what is still open.
Text checked against the code and documentation on .
The assistant is public and unauthenticated, so any visitor can send it any text. The design assumption is that the model can be talked into anything. Controls therefore sit in server code that the model cannot change, and the system prompt is advice, not enforcement.
Threats and controls
| Threat | Control | Checked by |
|---|---|---|
| A visitor asks the model to ignore its rules or reveal its instructions | The server drops any text written before a tool returned real portfolio content, so a leak on the first turn never reaches the visitor. The scorer also fails any answer that repeats a stretch of the instructions. | Prompt-injection cases; instruction-leak check on every case |
| A visitor tries to make the model call a tool that is not offered, such as a delete or email tool | Tool names are an allowlist. An unknown name is rejected before anything runs. | Prompt-injection cases that assert the forbidden tool did not run |
| The model invents a source or cites a real record it never looked up | A citation counts only if a tool in this request returned the ID. Rejected citations are dropped and flagged. | Citation-validity cases |
| The model writes a link, or a result card names a page that does not exist | Links come only from the server. Card links must pass the published-page allowlist or be approved sources. | Navigation and result-block cases; valid-navigation metric |
| Private or unpublished facts reach an answer, such as salary, phone number, or unpublished projects | Tools read a public-only registry that is filtered twice. Restricted records cannot be found by ID, search, or relationship. Unknown facts get a fixed reply. | Private-data and unknown-fact cases; restricted-record check on every case |
| Operational logs capture prompts or answers | Telemetry events have typed fields with no free text. They record IDs, timings, statuses, and token counts. | Telemetry check on every case |
| Cost abuse: a visitor spends the free model allowance | Per-visitor hourly limit, one request at a time, an app-wide daily budget, a step cap, an output cap, and a timeout. The route fails closed to static navigation. | Failure-handling cases cover the budget and provider failures |
Prompt injection in content
Retrieved content is data, never instructions. The corpus is first-party and typed, written and reviewed by the site owner. The assistant does not crawl pages or read documents a visitor supplies, so there is no channel for a third party to plant instructions in what it retrieves. If that changes, this assessment must be redone.
What this model does not cover
- A model can still write a false sentence next to a valid citation. Evaluation scores this with forbidden-claim patterns and reports the count; it is not a proof of truth.
- The rate limit is per server instance. Several instances can each allow a visitor, so the limit is weaker than it reads until a shared store is added.
- Forwarding headers decide a visitor's identity only when the app runs on Vercel. Elsewhere all visitors share one bucket. This has not been verified on a deployment.
- Chat history sent by the browser cannot be signed, so earlier assistant turns are treated as untrusted and facts must come from tools.
- No third-party security review has been done.