| name | security-owasp |
| description | OWASP Top 10:2025 kodenivå-mønstre for Kotlin, Go, Java og Node.js — tilgangskontroll, forsyningskjede, injeksjon og feilhåndtering |
| license | MIT |
| metadata | {"domain":"auth","tags":"security owasp kotlin go java nodejs nais supply-chain"} |
OWASP Top 10:2025 — kodenivå-sikkerhet
Taktiske sikkerhetsmønstre for Kotlin, Go, Java og Node.js på Nais, tilpasset OWASP Top 10:2025.
Utfyller @security-champion-agent (arkitekturnivå trusselmodellering) og security-review-skillen (skanneverktøy).
Fullstendige kodeeksempler for hver kategori: se examples.md i denne skill-mappen.
A01: Broken Access Control (inkl. SSRF)
get("/api/vedtak/{id}") {
val vedtak = vedtakRepository.findById(call.parameters["id"]!!.toLong())
call.respond(vedtak)
}
get("/api/vedtak/{id}") {
val bruker = call.hentBruker()
val vedtak = vedtakRepository.findById(call.parameters["id"]!!.toLong())
?: return@get call.respond(HttpStatusCode.NotFound)
if (vedtak.brukerId != bruker.id) return@get call.respond(HttpStatusCode.Forbidden)
call.respond(vedtak.toDTO())
}
func fetchExternal(targetURL string) error {
parsed, err := url.Parse(targetURL)
if err != nil { return err }
if !isAllowedHost(parsed.Host) { return fmt.Errorf("host not allowed: %s", parsed.Host) }
}
- Deny by default — krev eksplisitte tilganger, ikke eksplisitte avslag
- Ressursnivå-sjekker — ikke bare «er innlogget», men «eier denne ressursen»
- M2M-tokens — valider
azp-claim mot AZURE_APP_PRE_AUTHORIZED_APPS
- SSRF — valider utgående URL-er; bruk Nais
accessPolicy.outbound som defense-in-depth
A02: Security Misconfiguration
install(CORS) { anyHost() }
install(CORS) { allowHost("my-app.intern.nav.no", schemes = listOf("https")) }
mux.HandleFunc("/debug/pprof/", pprof.Index)
internalMux := http.NewServeMux()
internalMux.HandleFunc("/debug/pprof/", pprof.Index)
go http.ListenAndServe(":9090", internalMux)
- CORS begrenset til kjente origins — aldri
* eller anyHost()
- Debug-/admin-endepunkter skal ikke ligge på offentlig ingress
- Feilresponser saneres — ingen stack traces, SQL-feil eller filstier til klienten
- Default-deny Nais
accessPolicy — kun eksplisitt inbound/outbound
A03: Software Supply Chain Failures (NY i 2025)
require (
golang.org/x/crypto v0.31.0
github.com/jackc/pgx/v5 v5.7.2
)
dependencyLocking { lockAllConfigurations() }
dependencyManagement {
imports { mavenBom("org.springframework.boot:spring-boot-dependencies:3.4.1") }
}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@main
- Pin alle avhengigheter til eksakte versjoner; bruk lockfiles
- Skann avhengigheter:
govulncheck ./..., trivy repo ., ./gradlew dependencyCheckAnalyze
- GitHub Actions pinnet til full commit-SHA (ikke tags)
- Generer SBOM for produksjonsartefakter der det er mulig
- Foretrekk godt vedlikeholdte, first-party pakker
A04: Cryptographic Failures
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
client := &http.Client{}
val hash = MessageDigest.getInstance("MD5").digest(password.toByteArray())
val hashed = BCrypt.hashpw(password, BCrypt.gensalt(12))
- Passord: bcrypt (cost ≥ 12) eller argon2id — aldri MD5/SHA-1/SHA-256
- Hemmeligheter: alltid fra Nais-miljøvariabler eller Secret-ressurser — aldri hardkodet
- TLS 1.2+: sett aldri
InsecureSkipVerify: true
- Kryptering: AES-256-GCM; roter nøkler jevnlig
A05: Injection
session.run(queryOf("SELECT * FROM vedtak WHERE status = '$status'").map { ... }.asList)
session.run(queryOf("SELECT * FROM vedtak WHERE status = ?", status).map { ... }.asList)
exec.Command("sh", "-c", fmt.Sprintf("process %s", userInput)).Run()
exec.Command("process", userInput).Run()
- Alle SQL-spørringer parameterisert (
? / $1) — aldri strengkonkatenering
- Ingen shell-kjøring med brukerkontrollert input
- Valider/saner all ekstern input ved tjenestegrensen
A09: Security Logging and Alerting Failures
log.info("Vedtak opprettet", kv("vedtakId", vedtak.id), kv("sakId", sak.id))
log.info("Vedtak for bruker ${bruker.fnr}")
- Ingen PII i logg (fnr, navn, adresse, tokens)
- Sporingslogg for sensitive operasjoner (vedtak, utbetaling, tilgang)
- Korrelasjons-ID-er forplantes på tvers av tjenester (OpenTelemetry trace context)
- Varsling på avvikende mønstre (auth-feil, rate spikes)
A10: Mishandling of Exceptional Conditions (NY i 2025)
func processRequest(data []byte) Result {
var req Request
json.Unmarshal(data, &req)
return handle(req)
}
func processRequest(data []byte) (Result, error) {
var req Request
if err := json.Unmarshal(data, &req); err != nil {
return Result{}, fmt.Errorf("invalid request payload: %w", err)
}
return handle(req)
}
fun process(data: String): Result {
try { return parse(data) }
catch (e: Exception) { return Result.empty() }
}
fun process(data: String): Result {
return try { parse(data) }
catch (e: Exception) {
log.error("Parsing failed", kv("error", e.message))
throw ServiceException("Could not process input", e)
}
}
- Håndter alltid feil — ignorer aldri returnerte feil i Go
- Recover fra panics ved HTTP-handler-grensen (middleware)
- Feil trygt: nekt tilgang som standard når tilstanden er usikker
- Saner feilmeldinger: interne detaljer blir i loggen, ikke i responsen
- Sentralisert feilhåndtering via middleware/exception mappers
Hurtigsjekkliste
Relatert
| Ressurs | Bruk til |
|---|
security-review-skill | Pre-commit-skanning (trivy, zizmor, govulncheck) |
@security-champion-agent | Trusselmodellering, compliance, Navs sikkerhetsarkitektur |
@auth-agent | JWT-validering, TokenX, ID-porten-implementasjon |
threat-model-skill | STRIDE-A-analyse for nye tjenester |
| OWASP Top 10:2025 | Offisielle kategoribeskrivelser |
| OWASP Go SCP | Go-spesifikk veiledning for sikker koding |
| OWASP CI/CD Top 10 | Sikkerhetsrisikoer i pipeline |
| sikkerhet.nav.no | Navs Golden Path |
Grenser
✅ Alltid
- Parameteriserte spørringer for all SQL
- Ressursnivå-tilgangssjekker på alle datareturnerende endepunkter
- Strukturert logging uten PII
- SHA-pinnede GitHub Actions
- Eksplisitt feilhåndtering (ingen ignorerte feil)
- Avhengigheter skannet før release
⚠️ Spør først
- Egne kryptografiske implementasjoner
- Deaktivering av sikkerhetsfunksjoner for testing
- Endring av autentiserings- eller autorisasjonslogikk
- Nye utgående eksterne hosts
🚫 Aldri
- Strengkonkatenerte SQL-spørringer
InsecureSkipVerify: true i produksjon
- PII i loggutsagn (fnr, navn, adresse)
- Wildcard CORS (
* / anyHost())
- Hardkodede hemmeligheter eller krypteringsnøkler
- Flytende tags (
@main, @v3) for GitHub Actions
- Stille svelging av feil uten logging