Threat Model
STRIDE applied to the trust boundaries enumerated in trust boundaries. The three priority threats are listed first; the full STRIDE matrix follows.
Priority threats
Section titled “Priority threats”T1. Prompt injection via retrieved chunks (indirect)
Section titled “T1. Prompt injection via retrieved chunks (indirect)”- Boundary: the prompt-construction edge inside the API Lambda where third-party-origin chunks meet the prompt template (the in-process boundary; not a network hop).
- Mechanism: the corpus is
neural-bridge/rag-dataset-12000, Apache-2.0, authored by a third party. Any chunk can contain text shaped as instructions to the LLM (“ignore previous instructions and…”). When retrieval places that chunk into the system prompt verbatim, the model may follow those instructions. - Impact: answers diverge from grounded content; the model may reveal the system prompt, produce off-policy content, or emit attacker-chosen text the user attributes to the product.
- Likelihood today: low (curated public Q&A dataset), but the architecture cannot distinguish a friendly corpus from a hostile one. Likelihood becomes high the day the corpus is swapped.
- Mitigations:
- Today: clearly delimit retrieved content in the prompt (e.g. fenced blocks); add an explicit instruction that any imperative text inside the delimiters is data, not instructions; log prompt + response for review.
- Capability #44 / Decision #55 (closed): Safety Gate via Bedrock Guardrails evaluates the generated answer before return.
- Defense in depth: never echo retrieved content into a tool-use or function-call argument (we currently call neither — guardrail for the future).
T2. Direct prompt injection via /query body
Section titled “T2. Direct prompt injection via /query body”- Boundary: Browser → API Gateway → Lambda (the user-supplied
questionfield). - Mechanism: the user submits a
questionthat contains adversarial prompt content. Without input shaping, the model receives ”${SYSTEM}\n${QUESTION}” with the user’s text potentially containing role markers, jailbreak templates, or instructions to leak the system prompt. - Impact: same class as T1, but originated by the requester. Lower stakes since the requester is also the audience, but matters if the answer is shared, screenshotted, or logged.
- Mitigations:
- Cap question length (HTTP 422 on oversized is in retrieval spec; confirm the cap is e.g. 2KB, not arbitrary).
- Strip or escape control characters; never interpolate the question into the system prompt block.
- Rely on the same Safety Gate path as T1 for output-side mitigation.
T3. PII / sensitive-data exfiltration if the corpus is ever swapped
Section titled “T3. PII / sensitive-data exfiltration if the corpus is ever swapped”- Boundary: ingestion → Aurora; ingestion → Bedrock embeddings.
- Mechanism: the architecture treats the corpus as one data class (data classification). If a future operator points ingestion at a corpus containing PII, secrets, or internal documents, the existing pipeline embeds that content via Bedrock and stores it in pgvector. The
/queryendpoint is then an exfiltration interface for whatever is in the table, gated only by an operator-issued bearer token with a per-key lifetime request quota, and by a self-service demo key once Story #280 lands. - Impact: depending on the swapped corpus, ranges from embarrassing to a notifiable breach.
- Mitigations:
- Today: the data-classification rule (one class today; reclassification triggers a re-review) is the gate. No automated control prevents an operator from pointing the pipeline elsewhere.
- Before any reclassification: output filtering, retention/deletion policy, a key-management review beyond the capped demo key, and a compliance scope reassessment (compliance).
Full STRIDE matrix
Section titled “Full STRIDE matrix”S = Spoofing, T = Tampering, R = Repudiation, I = Information disclosure, D = Denial of service, E = Elevation of privilege.
| Boundary / asset | S | T | R | I | D | E | Notes |
|---|---|---|---|---|---|---|---|
| Browser -> API Gateway | M | L | L | L | M | L | TLS terminates at API Gateway. POST /query requires a bearer token validated by the Authorizer Lambda (RAG009), so spoofing means presenting a key issued to someone else; the per-key lifetime request quota bounds what that buys. /healthz is unauthenticated by design. DoS mitigated by the route-level API Gateway throttle on POST /query, live under Story #65 (see assessment, Controls in place). |
| API Gateway -> Lambda | L | L | L | L | L | L | AWS-managed integration; SigV4 not user-controllable. |
| Lambda -> RDS Data API | L | L | L | L | L | L | IAM-authed HTTPS; least-privilege role; statements parameterized. |
| Lambda -> Bedrock | L | M | L | M | M | L | Tampering and disclosure manifest as T1/T2 above. DoS is the cost-runaway shape — needs token-spend alarm (gap). |
| Prompt construction (in-Lambda) | n/a | H | L | M | L | L | T1 lives here. The “tampering” is corpus-origin instructions altering model behavior. |
| Lambda -> Secrets Manager | L | L | L | L | L | L | IAM-scoped to one secret ARN; credentials never leave Lambda memory. |
| Aurora at rest | L | L | L | L | L | L | KMS-encrypted; no public endpoint; security group denies inbound except Data API service. |
| Ingestion -> Hugging Face | M | M | L | L | L | L | Upstream integrity is implicit trust today. Pin dataset revision SHA if ingestion ever becomes unattended (gap in assessment). |
| Ingestion -> Aurora | L | L | L | L | L | L | Same control surface as the API Lambda path. |
| CloudFront / S3 SPA | L | L | L | L | L | L | Public static assets; no secrets in the bundle (VITE_API_URL is a public URL). |
| CI -> AWS (Terraform apply) | M | M | M | L | L | H | GitHub Environment + manual Prod gate (RAG001) constrains who can apply; OIDC role with environment-scoped trust policy is the implementation expectation. |
Legend: L = low, M = medium, H = high. “L” everywhere is not “no risk”; it is “addressed by an explicit control or accepted explicitly”.
What is not covered
Section titled “What is not covered”- Physical security of the operator’s machine (out of scope; local dev environment).
- AWS-managed-service internals (Bedrock model weights, Aurora storage layer).
- Browser-side threats against the operator’s own session (XSS, CSRF) — the only client state is the demo bearer key the user pastes in, capped by its lifetime request quota, plus the question + answer pair on the page.
A re-run of this threat model is warranted when any of these change: the key model moves beyond the capped demo key, the corpus is reclassified, a Safety Gate is implemented, or Lambda moves into a VPC (RAG004 revisit).
© 2026 Benjamin Arunski