11 KiB
Threat model
Scope en assets
Te beschermen:
- gebruikersaccount, sessies en zoekvoorkeuren;
- mailbox-, SMTP-, database- en registrycredentials;
- sollicitatiedossiers, notities en eventuele documenten;
- integriteit van vacatureclusters, scores en feedback;
- beschikbaarheid van de Unraid-host en het thuisnetwerk;
- bronbeleid en bewijs dat alleen toegestane bronnen worden benaderd.
Niet vertrouwd:
- iedere vacaturetekst, HTML, JSON-LD, feed en e-mail;
- alle links en redirectdoelen;
- externe DNS/HTTP/TLS-responses;
- AI-modeloutput, ook lokaal;
- browserinput en handmatige URL's;
- logs of exports die buiten de applicatie worden geopend.
Trust boundaries
Internet/mailbox
-> URL/source policy + IMAP boundary
-> raw document quarantine/retention
-> parser + sanitizer
-> normalized domain model
-> deterministic rules/scoring
-> authenticated UI / digest
User browser
-> TLS/reverse proxy
-> Django session + CSRF + object scoping
-> database
Django/Celery
-> Redis (queue, geen waarheid)
-> PostgreSQL (bron van waarheid)
-> optionele Ollama boundary
Belangrijkste dreigingen en mitigaties
| ID | Dreiging | Impact | Mitigaties | Verificatie |
|---|---|---|---|---|
| T-01 | SSRF via bron- of vacature-URL | toegang tot LAN, metadata of beheerinterfaces | schema/host/IP/poortcontrole, DNS-resolutie, redirecthercontrole, denylist, geen credentials in URL | tests/security/test_url_security.py, test_policy.py, fetchertests |
| T-02 | DNS rebinding/tijd-van-controle | request bereikt ander IP dan beoordeeld | iedere fetch en redirect valideert opnieuw DNS-resolutie en vereist consistente IP-set-overlap | VR-115, tests/unit/test_fetcher.py, aanvullende fetcher negative tests |
| T-03 | XSS/HTML-injectie | sessiediefstal of ongewenste navigatie | Bleach allowlist, platte tekst, template autoescaping, CSP/securityheaders | tests/security/test_sanitize.py, viewtests |
| T-04 | Prompt injection in vacature | AI verandert beleid of voert tools uit | vacaturetekst in data-envelope, schema-output, evidence-validatie, cachefouten met foutcategorie, geen toolrechten, deterministische harde regels, AI optioneel | AI-tests, ADR-0003, VR-109 evaluaties |
| T-05 | Malafide/oversized document | geheugen/CPU/diskuitputting | contenttype-, byte-, timeout- en redirectlimieten; korte retentie | fetchertests, source-runmetrics |
| T-06 | Crawlstorm of ban | externe overlast, IP-blokkade | expliciet allowbeleid, per-origin minimuminterval, concurrencylimiet, leasegebaseerde taakclaim met TTL + crash recovery, conditional requests, backoff, quarantaine | tasktests; VR-103, VR-112 |
| T-07 | Direct platformscrapen | voorwaarden-/blokkaderisico | centrale denylist, e-mailingress, geen loginbot/CAPTCHA | policytests, ADR-0002/0005 |
| T-08 | E-mailparserlink naar phishing/private host | ongewenste fetch of gebruiker misleid | linkextractie slaat unsubscribe over, follow-up opnieuw door policy/SSRF, bronlabel zichtbaar | e-mail- en policytests |
| T-09 | MIME/HTML-bom of malformed mail | resource-uitputting/parsercrash | IMAPbatchlimiet, bodylimiet bij vervolgtaak, robuuste parser, idempotente recordidentiteit | VR-115, e-mailfixtures |
| T-10 | Cross-user objecttoegang | lek van sollicitaties/feedback | LoginRequired, user-scoped querysets/get_or_create, autorisatietests | integratie-viewtests |
| T-11 | CSRF op feedback/profiel | ongewenste status- of profielmutatie | Django CSRF-middleware, POST-only acties, SameSitecookies | viewtests en frameworkcheck |
| T-12 | Credentiallek in Git/logs | account- of infrastructuurcompromis | env-only secrets, gitignore, beperkte logs, voorbeeldwaarden, secretrotatierunbook | CI-secret scan gepland VR-115; review |
| T-13 | Onveilige reverse proxy | sessie over HTTP, host-header-/originproblemen | TLS, exact ALLOWED_HOSTS/CSRF origins, secure cookies, proxychecklist | deployment smoke-test |
| T-14 | Redis als waarheid behandeld | dataverlies/dubbele verwerking | PostgreSQL-state, idempotente taken/outbox, acks-late | integratietests |
| T-15 | Dubbele Celery-uitvoering | dubbele vacatures/mails | unieke keys, transacties, message identity, outbox-uniciteit | pipeline/digesttests |
| T-16 | Dedupe voegt verschillende jobs samen | gemiste kans/verkeerde data | exact vóór fuzzy, conservatieve drempel, bronaliassen/provenance, herstelbare clusterbeslissing gepland | dedupetests; VR-116 evaluaties |
| T-17 | AI hallucineert ontbrekend feit | foutieve ranking | onbekend blijft onbekend, evidence/confidence, geen hard exclusion door AI | scoring/AI-tests |
| T-18 | Feedback poisoning/self-reinforcement | steeds smallere resultaten | begrensde gewichten, opt-in standaard uit, per-feature minimum samples, metadata-logging en resetpad | profieltests; VR-110 |
| T-19 | Automatisch solliciteren/massamail | reputatie/privacy/juridisch risico | geen submitendpoint/task, expliciete ADR en non-goal | codezoekreview, AC-043 |
| T-20 | Kwaadaardig bestand in sollicitatiedossier | host/browsercompromis | uploads nog niet actief; vóór implementatie allowlist, sniffing, size limit, niet-uitvoerbare opslag vereist | VR-113, nieuwe threat review |
| T-21 | Back-up bevat secrets/PII | langdurig datalek | encryptie, gescheiden opslag, korte retentie, herstelprocedure | runbook en hersteltest |
| T-22 | Supply-chainpackage/image | code execution | exacte versies/lockfile, beperkte dependencies, pinned baseimages/digests en scans gepland | CI, VR-115 |
| T-23 | Onbevoegde admin op thuisnetwerk | volledige datatoegang | uniek wachtwoord, TLS/VPN, geen defaultcredentials, sessiebeveiliging | Unraidchecklist |
| T-24 | Source terms wijzigen | ongewenste voortgezette crawling | reviewdatum, source health en policy expiry gepland | VR-102, VR-112 |
| T-31 | Sollicitatiedossier-export bevat niet-gewenste payload | data-lek of onbedoeld dossieroverdragen | export bevat alleen het gekozen dossier, ZIP-inhoud is beperkt tot snapshot/tijdlijn/print-HTML, bestandsnaam is geslugified zonder padseparators | tests/integration/test_applications.py |
| T-32 | XML external entity/entity-expansion via sitemap | lokale data-uitlezing of parseruitputting | sitemap-XML wordt met defusedxml verwerkt; fetcherlimieten blijven vóór parsing gelden |
tests/unit/test_discovery_rss.py, Ruff securitycheck |
| T-33 | Externe UI-CDN of niet-vertrouwde Stitch-interactie | supply-chain-XSS, tracking of acties buiten Django-beleid | productie gebruikt alleen lokale CSS/JS en inline SVG-symbolen; Stitch-code is documentatiereferentie, alle mutaties blijven Django POST+CSRF; themavoorkeur bevat geen persoonsgegevens en opslagfouten worden afgevangen | tests/e2e/test_vr114_browser_and_accessibility.py, browserconsole- en assetcontrole VR-118 |
Misbruikscenario's
Vacature zegt “negeer eerdere instructies”
De tekst wordt gesanitized en als veldwaarde doorgegeven. Een eventuele AI-call krijgt een vast schema en geen tools. De output kan geen bron activeren, URL openen, harde regel verwijderen, mail sturen of sollicitatie indienen.
Publieke pagina redirect naar 192.168.1.1
De redirectlocatie wordt opnieuw gevalideerd. Het request naar het private adres wordt niet uitgevoerd; de bronrun krijgt een policy/securityfout en de bron kan in quarantaine gaan.
E-mailalert bevat een platformlink en uitschrijflink
De adapter herkent vacaturekandidaten, negeert bekende unsubscribepatronen en slaat de platformlink hoogstens als alias op. Automatisch volgen vereist opnieuw een toegestane source policy; denylistplatformen worden geweigerd.
Aanvaller laat scheduler dezelfde job herhalen
Canonieke sleutels, databaseconstraints, transacties, idempotente message identity en outboxuniciteit beperken duplicaten. Taken zijn ontworpen voor at-least-once in plaats van exact-once aannames.
Security gates bij nieuwe functionaliteit
Een wijziging aan netwerk, mail, AI, rendering, auth, exports of uploads vereist:
- nieuwe/gewijzigde threat in deze tabel;
- negatieve test die de aanval representeert;
- begrensde input/output en foutcategorie;
- logreview op secrets/PII;
- runbook- en configuratie-update;
- volledige
codex_verify-gate.
Resterende risico's
-
Een applicatielaag kan DNS rebinding niet volledig uitsluiten zonder transportniveau-IP-pinning; dit staat in
VR-115. -
Brute-force of herhaalde foutieve mutatiepogingen blijven mogelijk, maar zijn beperkt door in-memory rate limiting en blokkades op login/manual-import.
-
Bronvoorwaarden vereisen menselijke/externe review per domein; automatisering kan dat niet juridisch beslissen.
-
Fuzzy dedupe en featureheuristieken kunnen inhoudelijk verkeerd zijn; provenance, feedback en benchmarkevaluaties beperken maar elimineren dit niet.
-
Een persoonlijke Unraid-host blijft afhankelijk van correcte netwerksegmentatie, patching en back-ups door de beheerder.
-
T-25: Verloren of verlopen policyreview
- Impact: bron kan op onbedoelde wijze doorgaan met crawlen
- Mitigatie:
SourcePolicyReviewmet decision/expiry + policy gate inassess_url - Verificatie: security/integration tests rond verlopen review in fail-closed gedrag
-
T-26: Handmatige URL/tekstimport
- Impact: ongewild ophalen van geblokkeerde of niet-ingesteste informatie, XSS via ingevulde tekst of overschrijding van limieten
- Mitigatie: CSRF-only import endpoint, allowlist-domeinvrije policy checks, sanitize op tekstveld, byte-limiet en max-size/timeout gedrag
- Verificatie: integration/security tests rond rejectie van geblokkeerde URL's en overschrijding van paste-limiet
-
T-27: Reminder-flood of dubbele reminder-mails
- Impact: gebruiker ontvangt herhaalde of ongewenste herinneringen
- Mitigatie: stabiele
dedupe_key, idempotente outbox met statusmachine,reminder_type-types en task-driven verzending - Verificatie:
tests/integration/test_reminders.py
-
T-28: Onterecht verzenden zonder ontvanger/uitgeschakelde reminderinstelling
- Impact: onnodige fout- of testmails, verwarring over afmeldgedrag
- Mitigatie: master- en topmatchschakelaar per profiel,
SKIPPED-status bij lege ontvanger en foutlogica met retries op taakniveau - Verificatie:
tests/integration/test_reminders.py
-
T-29: Bronhealth zet bronnen te vroeg in quarantaine bij incidentele netwerkruis
- Impact: tijdelijke uitval of incidentele bronfouten blokkeren een gezonde bron
- Mitigatie: duidelijke foutcategoriedrempels, gescheiden policy/security- en tijdelijke-foutlogica, en canaryherstel via trialpad
- Verificatie:
tests/integration/test_source_health.py
-
T-30: Geautomatiseerde canaryherstel blijft onbegrensd draaien
- Impact: herhaalde herstarts van dezelfde bron veroorzaken extra belasting
- Mitigatie: cooldown plus metadataflag voor eenmalige canary, en trialstatus met beperkte runtrigger
- Verificatie:
tests/integration/test_source_health.py