一键导入
security-review
Bruk før commit, push eller pull request for å sjekke at koden er trygg å merge
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Bruk før commit, push eller pull request for å sjekke at koden er trygg å merge
用 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 | security-review |
| description | Bruk før commit, push eller pull request for å sjekke at koden er trygg å merge |
| license | MIT |
| metadata | {"domain":"auth","tags":"security pre-commit vulnerability-scanning code-review"} |
This skill provides pre-commit and pre-PR security checks for Nav applications. Covers secret scanning, vulnerability scanning, and Nav-specific requirements.
For architecture questions, threat modeling, or compliance decisions, use @security-champion instead.
Run with run_in_terminal:
# Scan repo for known vulnerabilities and secrets
trivy repo .
# Scan Docker image for HIGH/CRITICAL CVEs
trivy image <image-name> --severity HIGH,CRITICAL
# Scan GitHub Actions workflows for insecure patterns
zizmor .github/workflows/
# Quick search for secrets in git history
git log -p --all -S 'password' -- '*.kt' '*.ts' | head -100
git log -p --all -S 'secret' -- '*.kt' '*.ts' | head -100
// ✅ Correct – parameterized query
fun findBruker(fnr: String): Bruker? =
jdbcTemplate.queryForObject(
"SELECT * FROM bruker WHERE fnr = ?",
brukerRowMapper,
fnr
)
// ❌ Wrong – SQL injection risk
fun findBrukerUnsafe(fnr: String): Bruker? =
jdbcTemplate.queryForObject(
"SELECT * FROM bruker WHERE fnr = '$fnr'",
brukerRowMapper
)
// ✅ Correct – log correlation ID, not PII
log.info("Behandler sak for bruker", kv("sakId", sak.id), kv("tema", sak.tema))
// ❌ Wrong – never log FNR, name, or other PII
log.info("Behandler sak for bruker ${bruker.fnr}") // GDPR violation
log.info("Navn: ${bruker.navn}") // GDPR violation
// ✅ Correct – read from environment (Nais injects via Secret)
val dbPassword = System.getenv("DB_PASSWORD")
?: throw IllegalStateException("DB_PASSWORD mangler")
// ❌ Wrong – hardcoded secret
val dbPassword = "supersecret123"
Only expose what must be exposed:
spec:
accessPolicy:
inbound:
rules:
- application: frontend-app # only explicitly named callers
outbound:
rules:
- application: pdl-api
namespace: pdl
cluster: prod-gcp
external:
- host: api.external-service.no # only if strictly necessary
// ✅ Correct — check that user has access to the resource
@GetMapping("/api/vedtak/{id}")
fun getVedtak(@PathVariable id: UUID): ResponseEntity<VedtakDTO> {
val bruker = hentInnloggetBruker()
val vedtak = vedtakService.findById(id)
if (vedtak.brukerId != bruker.id) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build()
}
return ResponseEntity.ok(vedtak.toDTO())
}
// ❌ Wrong — no access control (IDOR)
@GetMapping("/api/vedtak/{id}")
fun getVedtak(@PathVariable id: UUID) = vedtakService.findById(id)
// ✅ Correct — parameterized query
jdbcTemplate.query("SELECT * FROM bruker WHERE fnr = ?", mapper, fnr)
// ❌ Wrong — string concatenation
jdbcTemplate.query("SELECT * FROM bruker WHERE fnr = '$fnr'", mapper)
// ✅ Correct — CORS only for known domains
@Bean
fun corsFilter() = CorsFilter(CorsConfiguration().apply {
allowedOrigins = listOf("https://my-app.intern.nav.no")
allowedMethods = listOf("GET", "POST")
allowedHeaders = listOf("Authorization", "Content-Type")
})
// ❌ Wrong — open CORS
allowedOrigins = listOf("*")
// ✅ Correct — React escapes automatically
<BodyShort>{bruker.navn}</BodyShort>
// ❌ Wrong — raw HTML injection
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// ✅ Correct — validate input after deserialization
@PostMapping("/api/vedtak")
fun create(@RequestBody @Valid request: CreateVedtakRequest): ResponseEntity<VedtakDTO>
// ✅ Limit Jackson to known types
objectMapper.apply {
activateDefaultTyping(
polymorphicTypeValidator,
ObjectMapper.DefaultTyping.NON_FINAL
)
}
// ✅ Correct — structured logging with correlation ID, no PII
log.info("Vedtak opprettet", kv("vedtakId", vedtak.id), kv("sakId", sak.id))
// ❌ Wrong — PII in logs
log.info("Vedtak for bruker ${bruker.fnr} opprettet")
// ✅ Correct — validate file type, size, and magic bytes
fun validateUpload(file: MultipartFile) {
require(file.size <= 10 * 1024 * 1024) { "File too large (max 10 MB)" }
require(file.contentType in ALLOWED_TYPES) { "Invalid file type" }
val bytes = file.bytes.take(8).toByteArray()
require(verifyMagicBytes(bytes, file.contentType!!)) { "File content does not match type" }
}
private val ALLOWED_TYPES = setOf("application/pdf", "image/png", "image/jpeg")
// build.gradle.kts — pin versions, use BOM
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:3.4.1")
}
}
// Check vulnerable dependencies
// ./gradlew dependencyCheckAnalyze
// trivy repo .
dangerouslySetInnerHTML without sanitization# Kotlin – check for outdated/vulnerable dependencies
./gradlew dependencyUpdates
./gradlew dependencyCheckAnalyze # OWASP check
# Node/TypeScript
npm audit
npm audit fix
accessPolicy limits inbound/outbound to only what is needed@security-champion)azp against AZURE_APP_PRE_AUTHORIZED_APPS.nais/ accessPolicy inbound rules (no dead code or missing rules)trivy repo . passes without HIGH/CRITICAL findingszizmor passes on all GitHub Actions workflowsgit log scan above)dependencyUpdates / npm audit)| Resource | Use For |
|---|---|
@security-champion | Threat modeling, compliance questions, Nav security architecture |
@auth-agent | JWT validation, TokenX, ID-porten, Maskinporten |
@nais-agent | Nais manifest, accessPolicy, secrets setup |
| sikkerhet.nav.no | Nav Golden Path, authoritative security guidance |