بنقرة واحدة
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 |