> EthicsPortal's information-security risk register. Top risks assessed against the Service, current treatment, and residual position.

Source: https://ethicsportal.eu/policies/risk-register/
Updated: 2026-08-24

---

# Risk register

**Effective date:** 2026-05-21
**Last reviewed:** 2026-08-15
**Next review:** 2027-05-21
**Owner:** Yaroslav Shmarov, operator
**Version:** 1.1

This register lists the top information-security risks assessed against EthicsPortal, the treatment in place, and the residual position the operator has consciously accepted. It exists so that a controller, auditor, or procurement reviewer can verify that the most material risks have been thought about, not just the ones convenient to mention.

The register is a summary. The substantive treatment for each risk is documented on the [Security](/security/) page, in the [Data Processing Agreement](/dpa/), in the [Business continuity plan](/policies/business-continuity/), or in the [Information security policy](/policies/information-security/). The register's job is to make the trade-offs visible in one place.

---

## Assessment scale

| Level | Impact | Likelihood |
|---|---|---|
| Low | Single-customer inconvenience; no personal-data exposure | Not expected during the review window |
| Medium | Multi-customer service degradation, or personal-data exposure confined to operational metadata | Plausible during the review window |
| High | Confidentiality breach of reporter identity or report content; or extended unavailability of a covered surface | Reasonably foreseeable in absence of treatment |

The review window is twelve months from the effective date above.

---

## Residual-position vocabulary

- **Accepted.** The residual risk after treatment is acknowledged and accepted by the operator as a deliberate trade-off. The reasoning is stated.
- **Monitored.** The residual risk is acceptable today but is actively watched for change; specific indicators that would trigger re-treatment are stated.
- **In treatment.** The risk is not yet treated to the operator's target level. The current state, the target, and the timeline are stated openly.

---

## Register

### R-01. Operator incapacity / single-person-of-failure

| Field | Value |
|---|---|
| Inherent impact | High |
| Inherent likelihood | Medium |
| Treatment | Self-service PDF case export available to every organization admin without operator intervention. [DPA §6.8](/dpa/) deletion-and-return rights are enforceable independent of operator availability. Application is Kamal-deployed and portable to another EU operator. |
| Residual position | **In treatment.** A formal operator-incapacity protocol with a named legal contact is on the roadmap and not yet in place. See the [Business continuity plan §8](/policies/business-continuity/) for the full disclosure of what is and is not in place today. Controllers concerned about this gap are encouraged to take regular in-product exports. |

### R-02. Hetzner outage (primary infrastructure provider)

| Field | Value |
|---|---|
| Inherent impact | High |
| Inherent likelihood | Low |
| Treatment | Daily encrypted database dumps to Hetzner Object Storage (separate from compute host) plus Hetzner server-level snapshots; quarterly restore drills into a disposable environment ([Security#backups-and-restore](/security/#backups-and-restore)). Kamal deployment configuration is portable to an alternative EU provider for a prolonged-outage scenario. |
| Residual position | **Accepted.** A regional Hetzner outage may consume part of the 99.5% monthly SLA budget. Cross-provider hot failover is not in place because the additional sub-processor footprint, key-distribution surface, and operational complexity outweigh the marginal availability gain at the current customer footprint. Re-evaluated annually against the [SLA](/sla/) target. |

### R-03. Sub-processor personal-data breach

| Field | Value |
|---|---|
| Inherent impact | Medium--High (varies by sub-processor and data category) |
| Inherent likelihood | Low |
| Treatment | Minimization: each sub-processor receives only the personal-data category required for its function (see [Subprocessors](/subprocessors/) for the per-row breakdown). Encryption-at-rest under processor-managed keys means that a sub-processor with database access does not have plaintext access to report content or reporter identity ([Security#data-encryption](/security/#data-encryption)). 30-day sub-processor change notice and controller objection right ([DPA §6.4](/dpa/)). |
| Residual position | **Accepted.** No personal data covered by the DPA is transmitted to any sub-processor whose breach would expose reporter identity in plaintext. The reporter portal does not load Cloudflare; no LLM sub-processor exists. The residual risk is operational metadata (handler email, billing contact) at sub-processors whose breach would not compromise reporter confidentiality. |

### R-04. Operator credential theft / account compromise

| Field | Value |
|---|---|
| Inherent impact | High |
| Inherent likelihood | Low |
| Treatment | Hardware-backed two-factor authentication on all operator accounts that have production access (cloud provider, deployment, code hosting, email, password manager). Production database access requires the operator's authenticated session; credentials are not embedded in code or shared. Append-only audit log records all actions taken by any account, including the operator's, and cannot be edited by any user ([Security#audit-and-compliance](/security/#audit-and-compliance)). |
| Residual position | **Monitored.** The risk is materially lower than typical SaaS because there are no employee credentials to compromise --- the attack surface reduces to one identity. Monitored via AppSignal alerts for anomalous handler-portal authentication patterns. Trigger for re-treatment: a credible phishing attempt against the operator, or a CVE affecting the hardware-key path. |

### R-05. Restore failure during disaster recovery

| Field | Value |
|---|---|
| Inherent impact | High |
| Inherent likelihood | Low |
| Treatment | Two complementary backup layers (database dump and server-level snapshot) in independent retention scopes. Restore drill performed at least quarterly into a disposable environment; drill date is published on [Security#backups-and-restore](/security/#backups-and-restore). Restore procedure documented in the [Business continuity plan §6](/policies/business-continuity/). |
| Residual position | **Accepted.** RPO 24 hours and RTO 4 hours are stated in the [SLA](/sla/#recovery-objectives). Data written within the 24 hours preceding a catastrophic failure may be lost; this trade-off is disclosed. |

### R-06. Reporter network-side attribution leak (outside processor boundary)

| Field | Value |
|---|---|
| Inherent impact | Medium |
| Inherent likelihood | Medium |
| Treatment | The Service does not store reporter IP addresses in the database; rate limiting uses a one-way hash that is not reversible. Application logs for reporter routes are scrubbed. File uploads have metadata stripped (EXIF / GPS / author) server-side before storage. See [Security#anonymity-and-privacy](/security/#anonymity-and-privacy). |
| Residual position | **Accepted.** Network-side attribution (the reporter's ISP, the reporter's employer's egress proxy, a man-in-the-middle, or a corporate-device endpoint agent) is outside the processor boundary and cannot be controlled by the Service. Reporters are informed of this on the portal and may choose to report from a personal device on an external network, or via Tor. This residual is disclosed to reporters at the point of submission, which is the only place the trade-off can be acted upon. |

### R-07. Critical vulnerability in upstream dependency

| Field | Value |
|---|---|
| Inherent impact | Medium--High |
| Inherent likelihood | Medium |
| Treatment | Continuous SCA on every change: [Brakeman](https://brakemanscanner.org) for Rails-specific issues, [bundler-audit](https://github.com/rubysec/bundler-audit) for Ruby advisories, `importmap audit` for JavaScript imports, [Dependabot](https://docs.github.com/en/code-security/dependabot) for weekly grouped updates. End-of-life components are replaced before their upstream support window closes. See [Security#secure-development-lifecycle](/security/#secure-development-lifecycle) and [Security#dependency-and-patch-management](/security/#dependency-and-patch-management). Documented vulnerability-response timelines: critical 7 days, high 30 days, medium 90 days. |
| Residual position | **Monitored.** The Rails ecosystem is well-staffed for security disclosures. Trigger for re-treatment: a zero-day affecting Rails request-handling, ActiveRecord encryption, or PostgreSQL with no available patch. |

### R-08. Audit-log integrity compromise

| Field | Value |
|---|---|
| Inherent impact | High |
| Inherent likelihood | Low |
| Treatment | Audit-log entries are append-only and cannot be edited or selectively deleted by any application user, including organization administrators. PostgreSQL triggers reject changes to core audit content and table truncation even when Rails callbacks are bypassed; their presence is checked against the deployed database through the authenticated operational healthcheck. Required foreign-key nullification remains possible when a related record is erased, and entries are included in PDF case exports for regulatory review. See [Security#audit-and-compliance](/security/#audit-and-compliance). |
| Residual position | **Accepted.** The trail is not hash-chained, WORM-backed, or independently replicated. A privileged database operator could disable or drop the triggers, or issue a direct deletion outside the application-controlled retention and GDPR erasure paths. Production database access controls and the privileged-access procedure govern that residual risk; the public append-only claim is limited to application users and the protected database write paths described above. |

### R-09. Reporter passcode loss

| Field | Value |
|---|---|
| Inherent impact | Medium |
| Inherent likelihood | Medium (reporters are anonymous and may not have password-recovery channels) |
| Treatment | The 6-digit passcode is stored only as a bcrypt digest and cannot be recovered by the operator or by any handler. Reporters are informed at submission that the passcode is non-recoverable. Handlers may invite a reporter to re-submit or continue the conversation by an alternative channel. |
| Residual position | **Accepted by design.** Recoverability of the passcode is incompatible with the reporter-anonymity model: a recovery channel would require an identifier (email, phone) that defeats anonymity, or an operator-side reset that would allow the operator to impersonate the reporter. The trade-off is disclosed to reporters at the point of choosing the passcode. |

### R-10. Regulatory change requiring re-architecture

| Field | Value |
|---|---|
| Inherent impact | Medium--High |
| Inherent likelihood | Medium (Member-State transpositions and AI-Act delegated acts continue to evolve) |
| Treatment | Interpretive positions on ambiguous Directive 2019/1937 provisions are documented openly in the [Directive 2019/1937 interpretations](/directive-interpretations/), so a controller can verify alignment with their counsel's reading before subscribing. Per-country law summaries are published in [whistleblower laws by country](/whistleblower-laws/) and reviewed when national-law text changes. Material changes to processing (sub-processors, AI use, transfers) are notified to controllers under [DPA §6.4](/dpa/). |
| Residual position | **Monitored.** Trigger for re-treatment: ECJ judgment on a Directive 2019/1937 question that contradicts a published interpretation; CJEU judgment on international-transfer adequacy affecting an EU sub-processor; AI-Act delegated act extending obligations to AI-free processors. |

---

## Risks consciously not in this register

The following are recognized risk categories that this register deliberately omits because they are eliminated by design rather than treated:

- **AI / LLM exposure of report content.** No LLM, generative-AI, or AI-classifier service is engaged as a sub-processor. Report content is not transmitted to such services for any purpose. The attack surface (prompt injection, hallucinated compliance evidence, unauthorized retention by third parties) is therefore not present. Source: [DPA §6.10](/dpa/).
- **Reporter PII shared with handlers without justification.** The Service does not surface reporter IP, browser fingerprint, or device identifiers to handlers, because none of these are collected or stored.
- **Cross-tenant data leakage at the application layer.** Pundit-policy authorization is checked on every controller action; multi-tenant isolation is enforced at the request boundary, not via row-level visibility filters that can be bypassed.

If any of these design constraints changes, the risk re-enters this register.

---

## Review cadence

| Trigger | Action |
|---|---|
| Annual | Full review of every register row; residual positions re-affirmed or revised |
| Material architecture change | Affected rows reviewed and revised in the same change |
| Sub-processor added or replaced | R-03 reviewed; new row added if the change introduces a category not already represented |
| Material incident in the [incident register](/incidents/) | Root-cause-relevant rows reviewed; treatment updated if the incident revealed a control gap |
| Material change to the [Information security policy](/policies/information-security/) or [Business continuity plan](/policies/business-continuity/) | Affected rows reviewed for consistency |

Review actions are recorded in the document-control section below.

---

## Document control

| Field | Value |
|---|---|
| Document title | EthicsPortal Risk Register |
| Version | 1.1 |
| Effective date | 2026-05-21 |
| Last reviewed | 2026-08-15 |
| Next scheduled review | 2027-05-21 |
| Owner | Yaroslav Shmarov, operator |
| Distribution | Published on [ethicsportal.eu/policies/](/policies/) |

Signed: Yaroslav Shmarov, on behalf of EthicsPortal --- 2026-08-15.
