# Validering

## Hvad det er

Validering er det trin, hvor et program sammenholder indkommende data med de
regler, dataene skal følge, og afviser dem, når de ikke lever op til reglerne,
før noget bliver gemt, afviklet eller sendt videre. Det har flere navne
afhængigt af laget: inputvalidering for formularfelter og API-kald,
skemavalidering, når reglerne er skrevet ned som et JSON Schema eller en
OpenAPI-beskrivelse, og markupvalidering, når en webside tjekkes mod HTML's
grammatik. Input, der består, kaldes gyldigt.

OWASP's vejledning deler arbejdet op i to spørgsmål. Syntaks handler om,
hvorvidt en værdi har den forventede type og form: er det en dato, er det et
heltal, kan kroppen parses som JSON. Semantik handler om, hvorvidt værdien giver
mening for den konkrete handling, så en hotelbooking skal have to gyldige datoer
og desuden en slutdato efter startdatoen. At omsætte strengen »500« til et
heltal besvarer det første spørgsmål og siger intet om, hvorvidt 500 nætter er
et rimeligt ophold.

Markupvalidering er den ældste offentlige udgave af idéen på nettet. W3C's
Markup Validation Service beskriver validering som at tjekke et dokument mod den
grammatik, det selv hævder at bruge, og sammenligner sin validator med lint til
C. Dokumentationen er omhyggelig med, hvad det beviser: en gyldig side er ikke
nødvendigvis en god side, kun en side, som et værktøj har fundet i
overensstemmelse med et bestemt sæt regler. Den forsigtighed gælder alle de
andre slags. Validering fortæller, at dataene passer til de regler, man skrev,
og intet om, hvorvidt reglerne var de rigtige.

To nabobegreber bliver tit blandet sammen med det. Sanering ændrer input, så det
bliver acceptabelt, ved at fjerne eller omskrive dele af det, hvor validering
tager imod eller afviser input, som det er. Encoding og parametrisering gør data
sikre for det sted, de skal hen, en HTML-side eller en SQL-forespørgsel, og de
er stadig nødvendige, efter at valideringen er bestået.

## Hvorfor det betyder noget

Beslutningen bag validering er, hvor et system trækker sin tillidsgrænse, og
hvad det tjekker der. Hvert kald fra en browser, hver besked fra en kø, hver fil
fra en partner og hver konfigurationsændring fra en kollega kommer med
antagelser. Bliver antagelserne tjekket ved kanten, kan resten af koden regne
med dem; springes tjekket over, må hver funktion længere inde forsvare sig selv,
og i praksis gør de fleste det ikke.

Den anden beslutning er, hvordan reglerne skrives. Tjek, der er skrevet i hånden
endpoint for endpoint, er billige i starten og glider fra hinanden, efterhånden
som systemet vokser, fordi hvert tjek er sit eget lille stykke kode. Regler, der
er erklæret ét sted som typer eller som et skema, kan håndhæves af et bibliotek
og udgives som dokumentation fra samme kilde, så beskrivelsen og adfærden følges
ad. Prisen er et framework at lære og standardindstillinger at forstå, for et
skema håndhæver præcis det, det siger, og intet af det, det lader usagt.

Strenghed er det sidste valg. En allowlist beskriver, hvad der er acceptabelt,
og afviser alt andet, hvilket OWASP anbefaler frem for at forsøge at genkende
enhver ondsindet streng. At afvise felter, som valideringsskemaet ikke kender,
fanger slåfejl og forældede klienter tidligt. At afvise hele kaldet ved det
første problem, med en tydelig fejl, er sikrere end at fortsætte med data, der
kun er delvist tjekket.

## Sådan ser det ud i praksis

Virksomhedens API startede med request-validering skrevet i hånden for hvert
endpoint, og
[flytningen til Huma v2 gjorde tjekkene til typer på tværs af 649 paths og 760 operationer](/da/portfolio/migrated-the-http-api-from-fiber-to-huma-60/).
Hvert endpoint har nu input- og output-structs, Huma genererer
request-valideringen ud fra dem, og en OpenAPI-beskrivelse falder ud af de samme
typer. To WebSocket-endpoints bliver på rå Fiber, hvor Humas
request/response-model ikke passer. Et tjek i CI sammenligner de ruter, serveren
registrerer, med dem, beskrivelsen annoncerer, pariteten er 100 %, og den slags
fejl, hvor nogen glemte at tjekke et felt, forsvandt sammen med den håndskrevne
kode.

Konfiguration kræver samme behandling, og
[SSH-hærdningen på virksomhedens vært kører nu tre valideringstrin ved hver konvergering](/da/portfolio/hardened-ssh-with-three-stage-validation-111/).
Kandidatfilen syntakstjekkes, før den installeres, den samlede konfiguration
tjekkes efter installationen, og til sidst læses dæmonens egne resolverede
indstillinger tilbage, og 24 direktiver efterprøves mod dem. Det tredje trin
findes, fordi en adgangsrapport i september 2026 viste to indstillinger, som
automatiseringen havde skrevet ved hver konvergering, og som dæmonen havde
overskrevet, fordi styresystemets egne standarder blev læst først, og for de to
vinder den første forekomst. Som siden siger, beviser en søgning efter et
direktiv kun, at det blev skrevet.

Markupvalidering er også en del af rutinen:
[HTML-validering er et af tjekkene i en commit-gate med 22 lintere](/da/portfolio/built-a-22-linter-commit-gate-127/)
uden advarselsniveau, hvor hver diagnostik er en fejl, og inline-undertrykkelser
er forbudt, så en ugyldig side kommer kun igennem ved at blive rettet.

## Hvor det går galt

**Serveren stoler på det, browseren allerede har tjekket.** En formular, der
afviser en forkert e-mailadresse i browseren, ser valideret ud, men kaldet kan
sendes helt uden om formularen. OWASP nævner tjek, der kun sker i klienten, som
en almindelig faldgrube: valider på serveren, og brug browserens tjek som en
hurtig hjælp til den, der skriver.

**Et skema tager imod alt, det ikke nævner.** I JSON Schema gør det at nævne en
egenskab den hverken påkrævet eller forbyder andre felter, og med
standardvokabularet i 2020-12 bliver nøgleordet `format` samlet op som en
annotation, mens formattjek som standard er slået fra. Dette skema ser strengt
ud:

```json
{
    "type": "object",
    "properties": {
        "email": { "type": "string", "format": "email" }
    }
}
```

Det tager imod `{}`, `{"email": "nope"}` og `{"emial": "a@example.com"}`. Tilføj
`required` og `"additionalProperties": false`, og slå formatkontrol til i
validatoren, eller tjek formatet i koden. Huma afviser for sin del ukendte
felter i kroppen som standard, dokumenterer `readOnly` og `writeOnly` uden at
håndhæve dem og ignorerer ukendte query-parametre, medmindre man beder om andet.

**Tjekket består på én udgave af dataene, og programmet bruger en anden.** En
validator, der læser det rå kald, mens handleren læser en afkodet kopi, eller en
test, der kigger på filen på disken, mens dæmonen anvender en anden indstilling,
har tjekket noget, systemet aldrig bruger. OWASP's råd er at validere den
repræsentation, der faktisk bliver brugt. SSH-arbejdet ovenfor er samme lektie i
konfiguration: først dæmonens tilbagelæsning viste, hvad der rent faktisk
gjaldt.

**En denylist møder den næste variant.** At blokere kendte farlige tegn afviser
legitimt input, for eksempel en apostrof i et efternavn, og efterlader stadig
forespørgslen usikker. Fastlæg, hvad hvert felt accepterer, og afvis resten.

**Gyldigt input bliver behandlet som sikkert input.** En streng, der har bestået
hver eneste regel, kan stadig ødelægge en SQL-sætning eller en side, når den
sættes ind i den. Validering indsnævrer, hvad der kommer ind; parametriserede
forespørgsler og output-encoding beskytter det sted, hvor dataene ender, og
begge dele er nødvendige.

## Læs mere

- [OWASP Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
  — syntaks og semantik, allowlists, grænser for parsing og typiske faldgruber.
- [W3C Markup Validator documentation](https://validator.w3.org/docs/) —
  validatorens egen beskrivelse af markupvalidering, med hjælpesider om, hvad
  gyldighed beviser, og hvor grænsen går.
- [JSON Schema Validation, draft 2020-12](https://json-schema.org/draft/2020-12/json-schema-validation)
  — valideringsnøgleordene, herunder hvordan `format` opfører sig som standard.
- [Huma: Request Validation](https://huma.rocks/features/request-validation/) —
  validering genereret ud fra Go-struct-tags, med indstillingerne for strenge og
  løse felter.
- [OpenAPI Specification](https://spec.openapis.org/oas/latest.html) —
  beskrivelsesformatet, hvis skemaobjekter mange API-validatorer håndhæver.

<https://engineer.company/da/glossary/validation/>
