بنقرة واحدة
threat-model
STRIDE-A trusselmodellering for Nais-mikrotjenester — dataflyt, tillitsgrenser og risikovurdering
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
STRIDE-A trusselmodellering for Nais-mikrotjenester — dataflyt, tillitsgrenser og risikovurdering
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Generer conventional commit-meldinger med Nav-relevante scopes og breaking change-format
Expert builder for the Aksel design system (Nav / @navikt) React components, design tokens, layout primitives, theming (light/dark), icons, CSS, the Tailwind preset, version migrations, and Figma-to-code. Trigger on any frontend UI task that mentions Aksel, Nav/Navikt, "designsystemet", or @navikt/ds-* / @navikt/aksel-* packages — or that asks to add, create, build, or refactor a component (button, input, modal, table, alert, card, form) or layout, or to implement a design from Figma (a pasted figma.com/design/...?node-id link, "implement this design", "build this from Figma", design-to-code). Strong signals "using/with aksel", "@navikt/ds-react", "design system", a pasted figma.com link. If the work is frontend UI and there is any Aksel signal, invoke this skill unless the user explicitly opts out.
Integrer og konfigurer Nav Dekoratøren – felles header og footer for nav.no-applikasjoner. Bruk når et team skal ta i bruk Dekoratøren, oppdatere konfigurasjon, legge til breadcrumbs/språkvelger/analytics, håndtere samtykke (ekomloven), CSP eller feilsøke integrasjon mot dekoratøren.
Lag responsive layouts med Aksel Design System (v8+) - spacing tokens, layout primitives (Box, HStack, VStack, HGrid, Page, Bleed) og ResponsiveProp
Generer og kjør Playwright E2E-tester for webapplikasjoner med page objects, auth fixtures og tilgjengelighetstester
Kompakt output-stil som kutter fyllord og beholder teknisk substans — spar output-tokens uten å miste nøyaktighet.
| name | threat-model |
| description | STRIDE-A trusselmodellering for Nais-mikrotjenester — dataflyt, tillitsgrenser og risikovurdering |
| license | MIT |
| metadata | {"domain":"auth","tags":"threat-modeling stride security nais architecture"} |
Systematic threat identification for NAIS microservices using the STRIDE-A methodology. Produces a data flow diagram, structured threats table, prioritized mitigations, and residual risk summary.
Start by answering these questions to establish the threat model boundary:
Map the system using these element types:
| Symbol | Element | Example |
|---|---|---|
[External Entity] | User or external system | [Citizen Browser], [Partner API] |
(Process) | Your service or component | (dp-soknad), (dp-behandling) |
{Data Store} | Database, topic, bucket | {PostgreSQL}, {kafka: dp.soknad.v1}, {GCS Bucket} |
--> | Data flow | [User] --> (API) |
== boundary == | Trust boundary | == Internet/Ingress == |
[Citizen Browser]
|
| HTTPS (ID-porten login)
|
== Internet → Ingress (Wonderwall) ===========================
|
| Authorization header (JWT)
|
(dp-soknad-frontend)
|
| TokenX token exchange
|
== Frontend → Backend (TokenX validated) =====================
|
| REST/JSON + Bearer token
|
(dp-soknad-api)
|
|--- REST (Azure AD M2M) ---> (dp-behandling)
|
|--- Kafka produce ---------> {kafka: dp.soknad.v1}
| |
| | Kafka consume
| v
| (dp-mottak)
|
|--- SQL (Nais credentials) -> {PostgreSQL: dp-soknad-db}
|
|--- HTTPS (egress) --------> [External: Altinn API]
|
== Application → Database (mTLS, connection pooling) =========
== Application → Kafka (mTLS, schema registry) ===============
== Application → External (egress policy, HTTPS) =============
Identify these trust boundaries in every Nav threat model:
| Boundary | Transition | Security Mechanism |
|---|---|---|
| Internet → Ingress | External user to Nais | Wonderwall + ID-porten / Azure AD |
| Ingress → Application | Sidecar to app container | Token validation (JWT claims) |
| Application → Application | Service-to-service | TokenX token exchange / Azure AD M2M |
| Application → Kafka | App to message broker | mTLS (Nais-managed certs), schema validation |
| Application → Database | App to PostgreSQL | Nais-injected credentials, connection pooling |
| Application → External API | App to outside Nais | Egress policy, mutual TLS, API keys |
| GCP → On-prem | Cloud to legacy systems | NAV VPN / Private Service Connect |
Analyze each element and data flow against all seven threat categories.
Can an attacker impersonate a legitimate user or service?
Nav-specific threats:
azp (authorized party) validation on M2M tokenssub claim in test environments leaking to prodiss and aud validationDetection patterns:
// ✅ Correct — validate azp against pre-authorized apps
fun validateAzp(token: JWTClaimsSet) {
val azp = token.getStringClaim("azp")
val preAuthorized = System.getenv("AZURE_APP_PRE_AUTHORIZED_APPS")
require(azp in parsePreAuthorizedApps(preAuthorized)) {
"Unauthorized client: $azp"
}
}
// ❌ Vulnerable — only checks signature, not authorized party
fun validateToken(token: JWTClaimsSet) {
require(token.expirationTime.after(Date())) { "Token expired" }
// Missing: azp, iss, aud validation
}
Can an attacker modify data in transit or at rest?
Nav-specific threats:
Detection patterns:
// ✅ Correct — validate and sanitize input
data class SoknadRequest(
@field:Pattern(regexp = "^[0-9]{11}$") val fnr: String,
@field:Size(max = 500) val beskrivelse: String,
@field:NotNull val soknadsdato: LocalDate,
)
// ❌ Vulnerable — raw Map, no validation
@PostMapping("/api/soknad")
fun create(@RequestBody body: Map<String, Any>): ResponseEntity<*> {
repository.save(body) // no validation, no type safety
}
Can an actor deny performing an action?
Nav-specific threats:
Detection patterns:
// ✅ Correct — structured audit log with actor, action, resource
logger.info(
"Vedtak fattet",
kv("action", "vedtak.opprettet"),
kv("actor", saksbehandler.navIdent),
kv("vedtakId", vedtak.id),
kv("sakId", sak.id),
kv("correlationId", MDC.get("x-correlation-id")),
// Never log PII — fnr, name, address
)
// ❌ Insufficient — no actor, no correlation, PII leaked
logger.info("Vedtak opprettet for bruker ${bruker.fnr}")
Can an attacker access data they should not see?
Nav-specific threats:
Detection patterns:
// ✅ Correct — return only what the consumer needs
data class VedtakResponse(
val vedtakId: UUID,
val status: String,
val dato: LocalDate,
// No FNR, no internal IDs, no sensitive details
)
// ❌ Vulnerable — returns entire entity including PII
@GetMapping("/api/vedtak/{id}")
fun getVedtak(@PathVariable id: UUID) = vedtakRepository.findById(id)
# ✅ Correct — app-specific Kafka ACL
spec:
kafka:
pool: nav-prod
streams: true
topics:
- topic: dp.soknad.v1
access: readwrite # only this app
# ❌ Vulnerable — overly broad topic access
Can an attacker degrade or disable the service?
Nav-specific threats:
Detection patterns:
# ✅ Correct — Nais resource limits and liveness probes
spec:
resources:
limits:
memory: 512Mi
requests:
cpu: 50m
memory: 256Mi
liveness:
path: /isalive
initialDelay: 10
timeout: 1
periodSeconds: 5
readiness:
path: /isready
initialDelay: 10
timeout: 1
// ✅ Correct — bounded query with pagination
fun findByIdent(ident: String, page: Int, size: Int = 50): List<Vedtak> {
require(size <= 100) { "Page size too large" }
return jdbcTemplate.query(
"SELECT * FROM vedtak WHERE ident = ? ORDER BY dato DESC LIMIT ? OFFSET ?",
vedtakMapper, ident, size, page * size
)
}
// ❌ Vulnerable — unbounded query
fun findByIdent(ident: String) = jdbcTemplate.query(
"SELECT * FROM vedtak WHERE ident = ?", vedtakMapper, ident
)
Can an attacker gain access they should not have?
Nav-specific threats:
Detection patterns:
// ✅ Correct — resource-level ownership check
@GetMapping("/api/vedtak/{id}")
fun getVedtak(@PathVariable id: UUID): ResponseEntity<VedtakDTO> {
val bruker = hentInnloggetBruker()
val vedtak = vedtakService.findById(id)
?: return ResponseEntity.notFound().build()
if (vedtak.brukerId != bruker.id) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build()
}
return ResponseEntity.ok(vedtak.toDTO())
}
// ❌ Vulnerable — IDOR, no ownership check
@GetMapping("/api/vedtak/{id}")
fun getVedtak(@PathVariable id: UUID) =
ResponseEntity.ok(vedtakService.findById(id))
Can an attacker misuse legitimate functionality?
Nav-specific threats:
Detection patterns:
// ✅ Correct — idempotency key prevents duplicates
@PostMapping("/api/soknad")
fun submitSoknad(
@RequestHeader("Idempotency-Key") idempotencyKey: String,
@RequestBody request: SoknadRequest,
): ResponseEntity<SoknadResponse> {
val existing = soknadService.findByIdempotencyKey(idempotencyKey)
if (existing != null) {
return ResponseEntity.ok(existing.toResponse())
}
val soknad = soknadService.create(request, idempotencyKey)
return ResponseEntity.status(HttpStatus.CREATED).body(soknad.toResponse())
}
// ❌ Vulnerable — no idempotency, allows duplicate submissions
@PostMapping("/api/soknad")
fun submitSoknad(@RequestBody request: SoknadRequest) =
ResponseEntity.ok(soknadService.create(request))
Rate each identified threat using severity levels:
| Severity | Description | Criteria |
|---|---|---|
| Critical | Immediate exploitation risk | PII breach, auth bypass, data corruption at scale |
| High | Significant impact if exploited | IDOR, missing access control, unvalidated input on sensitive endpoints |
| Medium | Moderate impact, requires conditions | Missing rate limiting, verbose error messages, broad Kafka ACLs |
| Low | Minimal impact or unlikely | Missing HSTS headers, informational log leakage |
Document every identified threat in this format:
| ID | Element | STRIDE | Threat | Severity | Mitigation | Status |
|----|---------|--------|--------|----------|------------|--------|
| T1 | API Gateway | S | Forged JWT bypasses auth | Critical | Validate `iss`, `aud`, `exp`, `azp` claims | ☐ |
| T2 | dp-soknad-api | T | Unvalidated request body | High | Add `@Valid` + request DTO with constraints | ☐ |
| T3 | Kafka producer | T | Unsigned messages | Medium | Enable schema registry validation | ☐ |
| T4 | dp-soknad-api | R | No audit trail for vedtak | High | Add structured audit logging with actor + correlationId | ☐ |
| T5 | API response | I | PII in error responses | High | Use ProblemDetail, strip stack traces in prod | ☐ |
| T6 | PostgreSQL | I | Overly broad query results | Medium | Return DTOs with only required fields | ☐ |
| T7 | Public endpoint | D | No rate limiting | Medium | Add rate limiter (token bucket, 100 req/min) | ☐ |
| T8 | GET /vedtak/{id} | E | IDOR — no ownership check | Critical | Add resource-level access control | ☐ |
| T9 | POST /soknad | A | Duplicate submissions | Medium | Implement idempotency key pattern | ☐ |
Status legend: ☐ Open, ☑ Mitigated, ◐ In Progress, ⊘ Accepted Risk
Map threats to concrete Nav platform mitigations. Six areas to cover:
iss, aud, exp, azp)accessPolicy inbound/outbound allow-lists, egress restrictionsSee references/nav-mitigations.md for code examples of each mitigation area.
The completed threat model should include these four deliverables:
Text-based DFD showing all elements, data flows, and trust boundaries (see Step 2).
Complete table with all identified threats across STRIDE-A categories (see Step 4).
Ordered list of mitigations, grouped by priority:
### P0 — Fix Immediately
- [ ] T1: Validate JWT claims (iss, aud, azp) on all protected endpoints
- [ ] T8: Add resource-level ownership check on GET /vedtak/{id}
### P1 — Fix Before Launch
- [ ] T2: Add request validation DTOs with Bean Validation
- [ ] T4: Implement structured audit logging for vedtak operations
- [ ] T5: Strip stack traces from error responses in prod
### P2 — Fix Soon
- [ ] T7: Add rate limiting on public endpoints
- [ ] T9: Implement idempotency key pattern for POST /soknad
- [ ] T3: Enable Kafka schema registry validation
Document risks that are accepted, transferred, or cannot be fully mitigated:
| Risk | Severity | Rationale | Owner | Review Date |
|------|----------|-----------|-------|-------------|
| Kafka message replay | Low | mTLS + consumer idempotency makes replay difficult | Team Dagpenger | 2025-Q3 |
| GCS bucket misconfiguration | Medium | Nais manages IAM; manual audit quarterly | Platform team | 2025-Q2 |
| Resource | Use For |
|---|---|
@security-champion-agent | Security architecture, compliance, Nav security culture |
security-review skill | Pre-commit scanning (trivy, zizmor, secrets) |
@auth-agent | JWT validation, TokenX, ID-porten implementation |
@nais-agent | accessPolicy, network policy, secrets management |
nav-architecture-review skill | Architecture Decision Records with security perspective |
| sikkerhet.nav.no | Nav Golden Path, authoritative security guidance |