| Property | Value |
|---|
| Controls | SID-OPS-08 |
| ASVS | V1.1 (Secure Software Development Lifecycle Requirements), V1.11 (Business Logic Architecture) |
| ISO 27001 | A.8.25 (Secure development lifecycle), A.8.27 (Secure system architecture and engineering principles) |
Purpose
This document provides a formal STRIDE threat model for the SIROS ID platform, covering the components
vc (credential issuer/verifier), go-trust (trust evaluation PDP), go-spocp (policy engine),
wallet-common (shared library), wallet-frontend (browser wallet UI), and go-wallet-backend
(wallet backend). It addresses the finding that security architecture documentation exists but no
structured threat model using a recognised methodology (STRIDE, attack trees) was maintained.
This document should be reviewed and updated for every significant design change or sprint planning cycle
per ASVS V1.1.6.
System Overview
The SIROS ID platform is a European Digital Identity Wallet (EUDIW) implementation. The following
components interact to deliver credential issuance, verification, trust evaluation, and wallet management.
Trust Boundaries
| Boundary | Crossing | Authentication |
|---|
| Internet → DMZ | Browser / external wallet → reverse proxy | TLS only |
| DMZ → Application | Reverse proxy → wallet backend / vc platform | TLS (operator-managed) |
| Application → Data | Wallet backend → MongoDB; vc → PostgreSQL | Optional mTLS |
| Application → Trust | Wallet backend → go-trust (AuthZEN) | None (network-level only) |
| Application → External | go-trust → TSL / DID / OIDF | TLS 1.2+ + SSRF protection |
| Biometric → Upstream | facetec-api → FaceTec Server | mTLS |
| Inter-service gRPC | vc components | mTLS (cert fingerprint + DN) |
STRIDE Analysis
The tables below enumerate threats per component and trust-boundary crossing. Each entry includes the
STRIDE category, a threat description, current mitigations, residual risk, and recommended actions.
Legend
| Rating | Meaning |
|---|
| Low | Mitigated; residual risk acceptable |
| Medium | Partially mitigated; additional controls recommended |
| High | Not adequately mitigated; remediation required |
1. Wallet Frontend (wallet-frontend)
1.1 Authentication / Session
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| WF-S-1 | Spoofing | Attacker replays a stolen JWT to impersonate a user | Short expiry (exp); JTI blacklist (in-memory); refresh token rotation | Low | Ensure JTI blacklist survives restart or use distributed blacklist |
| WF-S-2 | Spoofing | Phishing page mimics wallet UI to capture WebAuthn challenge | WebAuthn origin binding (RP ID = registered domain) | Low | Enforce strict RP ID; avoid wildcard subdomains |
| WF-I-1 | Info Disclosure | Session token extracted from sessionStorage via XSS | CSP (script-src 'self'); HttpOnly cookies not used (sessionStorage by design) — any XSS bypasses this boundary | Medium | Priority: next sprint — harden CSP to eliminate inline script; migrate token to HttpOnly + SameSite=Strict cookie to remove JS-accessible session token |
| WF-I-2 | Info Disclosure | Credential private keys exported from IndexedDB via XSS | Keys stored JWE-encrypted; decryption requires PRF-backed main key | Low | Maintain CSP hardening |
| WF-T-1 | Tampering | Attacker modifies WalletStateContainer stored on the backend | ETag optimistic locking (412 on conflict); JWE-encrypted container; event-chain parentHash integrity | Low | — |
| WF-R-1 | Repudiation | User denies signing a Verifiable Presentation | VP-JWT carries user DID and key reference; the signed VP itself provides cryptographic non-repudiation at the relying party | Low | Server-side logging of VP signing events is intentionally excluded — it would reveal which services the user presents credentials to, violating EUDI unlinkability and minimal disclosure principles; the signed VP-JWT is sufficient for non-repudiation |
| WF-D-1 | DoS | Flood WebSocket engine to exhaust server connections | Separate port 8082; JWT required on first message; connection rate-limited by reverse proxy | Low | Configure reverse proxy connection limits |
| WF-E-1 | Elevation | Attacker uses another tenant's JWT to access user data | tenant_id extracted from JWT claim (authoritative); disabled tenants rejected 403 | Low | — |
1.2 Key Material
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| WF-I-3 | Info Disclosure | WebAuthn PRF output intercepted during unlock | PRF output never transmitted; used in-memory for HKDF derivation only | Low | — |
| WF-T-2 | Tampering | Attacker injects a rogue ECDH public key to re-wrap the main key | Main key re-encryption uses ECDH ephemeral keypair generated in browser; server stores opaque blob only | Low | — |
| WF-E-2 | Elevation | Attacker forces schema downgrade (v2 → v1) to bypass ECDH wrapping | Format upgrade is client-driven; backend stores whatever the client submits | Medium | Validate minimum container schema version server-side |
2. Wallet Backend (go-wallet-backend)
2.1 User-Facing API (Port 8080)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| WB-S-1 | Spoofing | Attacker forges JWT to gain API access | HMAC-SHA256 signature verified on every request; iss/aud validated | Low | Rotate JWT signing secret on schedule |
| WB-S-2 | Spoofing | Attacker submits fabricated WebAuthn assertion for registration/login | Challenge validated single-use (5-min TTL); attestation verified; AAGUID blacklist | Low | — |
| WB-T-1 | Tampering | MITM modifies API request between reverse proxy and backend | TLS configured (cert_file/key_file); reverse proxy enforces TLS to public clients | Low | Enforce TLS on reverse-proxy → backend leg in production |
| WB-I-1 | Info Disclosure | Admin token logged at DEBUG level and shipped to log aggregator | Admin token debug logging already suppressed (go-wallet-backend#89) | Low | Verify fix is deployed in all production builds |
| WB-I-2 | Info Disclosure | MongoDB user records accessible without encryption at rest | MongoDB connection supports optional mTLS; at-rest encryption is operator responsibility | Medium | Document operator requirement to enable MongoDB encryption at rest |
| WB-R-1 | Repudiation | Operator denies tenant CRUD actions performed via admin API | Admin API on separate port with bearer token; no action-level audit log | Medium | Emit structured audit log for all admin API mutations |
| WB-D-1 | DoS | Brute-force WebAuthn login to trigger lockout for legitimate users | Sliding window rate limit: 10 attempts/60 s, 300 s lockout; failed attempts cost 2 tokens | Low | — |
| WB-D-2 | DoS | VCTM registry query flood (port 8097) | Per-tenant rate limit + shared anonymous pool (configurable RPM) | Low | Ensure anonymous pool limit is set conservatively in production |
| WB-E-1 | Elevation | Cross-tenant data access by manipulating X-Tenant-ID header | JWT tenant_id is authoritative; header ignored when JWT present | Low | — |
2.2 Admin API (Port 8081)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| WB-S-3 | Spoofing | Attacker guesses or brute-forces admin bearer token | 256-bit random token; constant-time comparison | Low | Enforce explicit token via env/file for production (do not use auto-generated) |
| WB-E-2 | Elevation | Network-reachable admin port grants full tenant/user CRUD | Admin API token authentication + operator-enforced exposure controls (Service/Ingress scope + NetworkPolicy) | Medium | Document and validate Kubernetes policy baseline for port 8081 as a deployment requirement |
| WB-D-3 | DoS | Admin API flooded to lock out legitimate administration | Operator network segmentation reduces exposure; no dedicated rate limit on admin port | Low | Add deployment-level rate limiting/WAF policy for admin endpoint where exposed |
2.3 AuthZEN Interface (go-trust)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| WB-S-4 | Spoofing | Attacker runs a rogue AuthZEN endpoint and redirects wallet backend | go-trust URL is operator-configured; not user-controlled | Low | Validate go-trust URL in deployment checklist |
| WB-E-3 | Elevation | Attacker calls go-trust /evaluation endpoint directly, bypassing SPOCP firewall | SPOCP firewall is fail-closed in production (GIN_MODE=release); /evaluation only evaluates publicly available trust information (TSL membership, OIDF trust anchors) — no user-specific or privileged data is returned | Low | Network-restrict go-trust to application zone as defence-in-depth; no application-layer authentication required given the public nature of the trust information |
3.1 API Gateway and Issuance
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| VC-S-1 | Spoofing | External wallet presents forged OID4VCI authorization code | Authorization code bound to PKCE challenge; single-use code validation | Low | — |
| VC-S-2 | Spoofing | Attacker spoofs facetec-api to inject biometric approval | facetec-api → apigw uses mTLS + bearer token; both required | Low | — |
| VC-T-1 | Tampering | Tamper with credential claims between issuer and registry | Internal HTTP (issuer → registry) lacks TLS in some configs; gRPC mTLS available | Medium | Enforce mTLS on issuer → registry HTTP paths; prefer gRPC mTLS only |
| VC-I-1 | Info Disclosure | PID or biometric data exposed in vc issuer logs | Credential claims passed in-process; log level controls | Medium | Audit log output of issuer and registry for PII; enforce structured logging with field redaction |
| VC-R-1 | Repudiation | Holder denies receiving a credential | Issuance recorded in registry with holder DID and timestamp | Low | — |
| VC-D-1 | DoS | OID4VCI token endpoint flooded | Token endpoint rate-limited (20/min per IP) in verifier; apigw limits not documented | Medium | Implement per-IP rate limiting on all apigw public endpoints |
| VC-E-1 | Elevation | SPOCP policy bypass on pid_auth credential type | pid_auth requires presenting valid PID credential; SPOCP S-expression policy enforces paths/methods | Low | — |
3.2 HSM / Key Management
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| VC-I-2 | Info Disclosure | PKCS#11 HSM PIN exposed in YAML config | Documented risk; operators advised to use secrets manager | Medium | Provide vault/env-var integration for HSM PIN per GEN-7.5-02 |
| VC-I-3 | Info Disclosure | Software fallback issuer key (PEM file) readable | Plaintext at rest; documented risk | High | Prohibit software fallback keys in production; require HSM mode per GEN-7.5-02 |
| VC-T-2 | Tampering | Attacker replaces software PEM key file | Filesystem permissions only | High | Use HSM mode; if software key required, use sealed-secret or vault-injected file |
4. Trust Evaluation (go-trust)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| TR-S-1 | Spoofing | DNS hijacking returns attacker-controlled trust list URL | SafeHTTPClient DNS rebinding protection; HTTPS required | Low | — |
| TR-S-2 | Spoofing | BGP hijacking routes ETSI TSL traffic to attacker | SafeHTTPClient enforces TLS 1.2+ with hardened cipher suites; X.509 chain validation | Low | Consider certificate pinning for known TSL endpoints |
| TR-T-1 | Tampering | Attacker injects malicious entries into fetched trust list | JWS signature verification on LoTE; X.509 chain validation on x5c | Low | — |
| TR-I-1 | Info Disclosure | /evaluation endpoint called externally to learn trust topology | The endpoint evaluates only publicly available trust information (ETSI TSL membership, OpenID Federation trust anchors, DID documents); no user identity, subject data, or non-public policy is exposed | Low | Network-restrict to application zone as defence-in-depth; authentication is not required given the intentionally public nature of the data |
| TR-D-1 | DoS | Flood /evaluation endpoint to deny trust decisions | Per-IP token bucket rate limiting (configurable RPS + burst) | Low | — |
| TR-D-2 | DoS | External trust service unavailable causes trust resolution failure | go-trust caches resolved trust lists | Low | Verify cache TTL is appropriate for TSL refresh schedules |
| TR-E-1 | Elevation | Attacker enumerates trust anchor membership via unauthenticated /evaluation | Trust anchor membership is derived from public ETSI TSLs and OIDF federation metadata; enumeration reveals no non-public information | Low | Network-restrict to application zone as defence-in-depth |
5. Policy Engine (go-spocp)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| SP-T-1 | Tampering | Attacker modifies startup-loaded configuration artifacts on disk | Configuration artifacts loaded at startup; file access controlled by OS | Medium | Sign or checksum startup-loaded configuration files; detect changes at startup |
| SP-E-1 | Elevation | Malformed S-expression input causes policy bypass | SPOCP parser is fail-closed; invalid expressions denied | Low | Fuzz-test S-expression parser for parser differentials |
| SP-R-1 | Repudiation | Operator denies configuration changes | No audit log for configuration file changes | Medium | Log configuration hash at startup; integrate configuration changes with SDLC change management |
6. Biometric Identity Verification (facetec-api)
| ID | STRIDE | Threat | Mitigations | Residual Risk | Action |
|---|
| FT-S-1 | Spoofing | Attacker replays biometric session token to re-use completed liveness check | Session tokens are single-use; FaceTec server validates | Low | — |
| FT-I-1 | Info Disclosure | Biometric image data (selfie) persisted beyond processing | FaceTec SDK responsible for storage; facetec-api is stateless for image data | Medium | Confirm FaceTec data retention policy; document data processing agreement |
| FT-I-2 | Info Disclosure | Biometric data in PostgreSQL accessible without encryption at rest | At-rest encryption is operator responsibility | Medium | Require PostgreSQL encryption at rest as deployment prerequisite |
| FT-D-1 | DoS | Biometric endpoint flooded to exhaust FaceTec capacity | Per-IP rate limit + concurrency semaphore (MaxConcurrentBiometric); 503 when full; 10 MB body cap | Low | — |
| FT-D-2 | DoS | 10 MB selfie upload consumes bandwidth | Hard 10 MB cap enforced | Low | — |
Cross-Cutting Threats
| ID | STRIDE | Threat | Components | Mitigations | Residual Risk | Action |
|---|
| CC-I-1 | Info Disclosure | HMAC JWT secrets exposed via misconfigured config/env | wallet-backend, facetec-api | Operator responsibility; documented risk | Medium | Provide vault/secrets manager integration guidance |
| CC-R-1 | Repudiation | No platform-wide audit trail for security-relevant events | All | Component-level logs exist; no centralised SIEM | Medium | (centralised logging) |
| CC-D-1 | DoS | Kubernetes pod restarts clear in-memory JTI blacklist | wallet-backend | Short token expiry limits window | Medium | Use Redis-backed or distributed JTI blacklist for production HA |
| CC-T-1 | Tampering | Supply-chain attack via compromised dependency | All | Dependabot, Grype, CodeQL, govulncheck | Low | — |
| CC-S-1 | Spoofing | Attacker impersonates internal service (no service mesh) | All | mTLS where configured; network zone controls | Medium | Evaluate service mesh (e.g. Istio) for mutual authentication of all inter-service calls |
Threat Summary and Prioritisation
| Priority | Threat IDs | Rationale |
|---|
| High | VC-I-3, VC-T-2 | Software PEM issuer keys are plaintext at rest; active remediation required |
| Medium — Remediate Next Sprint | WF-I-1 | Session token in sessionStorage accessible to XSS; harden CSP; evaluate HttpOnly + SameSite=Strict cookie migration |
| Medium — Remediate Next Sprint | WB-R-1, WB-E-2 | Missing admin API audit log; admin port network exposure |
| Medium — Remediate Next Quarter | WF-E-2, VC-T-1, VC-D-1, VC-I-1, VC-I-2, SP-T-1, SP-R-1 | Schema version enforcement; issuer→registry TLS; API rate limiting; log PII; policy file integrity/audit |
| Medium — Operator Guidance | WB-I-2, FT-I-2, CC-I-1, CC-D-1 | MongoDB/PostgreSQL at-rest encryption; JWT secrets management; HA JTI blacklist |
| Low | All others | Adequately mitigated by existing controls |
Assumptions and Scope Limitations
- Reverse proxy / ingress is operator-managed and assumed to enforce TLS termination. Threats at the ingress layer are out of scope.
- Database at-rest encryption is operator responsibility. The platform does not perform application-layer encryption of database fields (except the wallet
privateData blob).
- Hardware Security Modules (HSM) are assumed in production for vc issuer keys per GEN-7.5-02. Software PEM fallback is documented as a high residual risk.
- go-spocp is embedded in go-wallet-backend; it does not expose a network interface and is not independently addressable.
- wallet-common is a shared library consumed by wallet-frontend and go-wallet-backend; threats are captured under those components.
- This model covers the current release of each component. Design changes must trigger a threat model review per ASVS V1.1.6.
Review Schedule
| Trigger | Action |
|---|
| Every sprint planning | Review open threat items; add new threats for planned features |
| New component or integration | Update system diagram and STRIDE tables |
| Security incident | Root-cause analysis mapped to STRIDE category; add or update threat entry |
| Annual | Full threat model refresh against ASVS V1.1 checklist |