๐ Security-by-Design for European Parliament Intelligence
๐ฏ Comprehensive Security Framework for Multi-Language News Platform
๐ Document Owner: CEO | ๐ Version: 2.2 | ๐
Last Updated:
2026-05-03 (UTC)
๐ Review Cycle: Annual | โฐ Next Review: 2027-05-03
๐ท๏ธ Classification: Public (Open Source European Parliament Monitoring
Platform)
| Document | Focus | Description | Documentation Link |
|---|---|---|---|
| Architecture | ๐๏ธ Architecture | C4 model showing current system structure | View Source |
| Future Architecture | ๐๏ธ Architecture | C4 model showing future system structure | View Source |
| Mindmaps | ๐ง Concept | Current system component relationships | View Source |
| Future Mindmaps | ๐ง Concept | Future capability evolution | View Source |
| SWOT Analysis | ๐ผ Business | Current strategic assessment | View Source |
| Future SWOT Analysis | ๐ผ Business | Future strategic opportunities | View Source |
| Data Model | ๐ Data | Current data structures and relationships | View Source |
| Future Data Model | ๐ Data | Enhanced European Parliament data architecture | View Source |
| Flowcharts | ๐ Process | Current data processing workflows | View Source |
| Future Flowcharts | ๐ Process | Enhanced AI-driven workflows | View Source |
| State Diagrams | ๐ Behavior | Current system state transitions | View Source |
| Future State Diagrams | ๐ Behavior | Enhanced adaptive state transitions | View Source |
| Security Architecture | ๐ก๏ธ Security | Current security implementation | View Source |
| Future Security Architecture | ๐ก๏ธ Security | Security enhancement roadmap | View Source |
| Threat Model | ๐ฏ Security | STRIDE threat analysis | View Source |
| Classification | ๐ท๏ธ Governance | CIA classification & BCP | View Source |
| CRA Assessment | ๐ก๏ธ Compliance | Cyber Resilience Act | View Source |
| Workflows | โ๏ธ DevOps | CI/CD documentation | View Source |
| Future Workflows | ๐ DevOps | Planned CI/CD enhancements | View Source |
| Business Continuity Plan | ๐ Resilience | Recovery planning | View Source |
| Financial Security Plan | ๐ฐ Financial | Cost & security analysis | View Source |
| End-of-Life Strategy | ๐ฆ Lifecycle | Technology EOL planning | View Source |
| Unit Test Plan | ๐งช Testing | Unit testing strategy | View Source |
| E2E Test Plan | ๐ Testing | End-to-end testing | View Source |
| Performance Testing | โก Performance | Performance benchmarks | View Source |
| Security Policy | ๐ Security | Vulnerability reporting & security policy | View Source |
EU Parliament Monitor is a static website generator that creates multi-language news articles about European Parliament activities. The system operates as an automated intelligence platform, generating news content through GitHub Actions workflows with minimal attack surface and public data transparency.
EU Parliament Monitor v0.8.54+ (post-2026-04-24 aggregator migration; Look-Ahead epic complete 2026-05-02) publishes 1927+ static HTML articles across 14 languages and 14 article types (breaking, week-ahead, week-in-review, month-ahead, month-in-review, quarter-ahead, quarter-in-review, year-ahead, year-in-review, term-outlook, election-cycle, committee-reports, motions, propositions), generated by 15 unified gh-aw agentic workflows (14 news-<type>.md article workflows + news-translate.md for 14-language flush translation). Per-slug stage budgets (including the minute โค 45 PR call deadline within the 60-min cap) are sourced from src/config/article-horizons.ts. Article HTML is rendered deterministically by src/aggregator/** from committed Stage-B analysis artifacts (analysis/daily/<date>/<slug>-run<NN>/) โ there is no AI-authored HTML step. The posture is validated by 3061+ automated tests across the test suite. Primary delivery is AWS S3 + CloudFront via OIDC federation; GitHub Pages remains the documented fallback. Release artifacts are signed with npm provenance and SLSA Level 3 build attestations. OpenSSF Scorecard + OpenSSF Best Practices #12068 certify the posture.
๐ Security Posture Change: Aggregator Migration (April 2026)
The April-2026 aggregator migration eliminated an entire class of agent-prose-injection defects at the root by removing the AI-authored HTML step. Template-prose leaks of the form that produced the
2026-04-20-motions-run46-en.htmlregression are no longer possible because there is no template-prose layer โ the aggregator reads committed markdown artifacts verbatim throughmarkdown-it+ the sanitiser insrc/utils/html-sanitize.ts. Residual risks have shifted:
- Malicious markdown in a committed artifact โ mitigated by
src/aggregator/clean-artifact.ts(front-matter strip, heading demote, ReDoS-safe relative-link rewrite, FNV-1a-hashed mermaid dedup) +src/utils/html-sanitize.ts(allowlist-based HTML sanitisation) +markdown-it's secure defaults (raw HTML disabled)- Mermaid XSS via committed diagram โ mitigated by the markdown-it mermaid-fence override that emits
<figure>wrappers only (diagram rendering is client-side via vendoredmermaid.esm.min.mjsloaded withscript-src 'self')- Purged validators โ
src/utils/content-validator.ts,src/utils/validate-articles.ts,src/utils/validate-analysis-completeness.ts, theFALLBACK_TEMPLATE_PATTERNSscanner, the Wave-2 OR-gate and Wave-3/Wave-4 strict IMF runtime gates. Enforcement moved to Stage-C agent-side review โ this is a defence-in-depth reduction that is safe because the root cause (AI-authored HTML) was removed in the same commit. Future regressions would need to surface as editorial quality gaps in the committed artifacts, which are reviewable in the analysis PR.
The platform automatically generates and publishes news articles covering:
Per Hack23 ISMS Classification Framework:
| Dimension | Level | Rationale |
|---|---|---|
| Confidentiality | Public (Level 1) | All data from European Parliament open data sources, no private information |
| Integrity | Medium (Level 2) | News accuracy critical for democratic transparency, incorrect information could mislead public |
| Availability | Medium (Level 2) | Daily updates expected, but 24-hour outages acceptable |
| RTO | 24 hours | Manual workflow trigger available, automated recovery via GitHub Actions |
| RPO | 1 day | Daily generation schedule, previous day's content acceptable |
Defense Strategy: Defense-in-depth with minimal attack surface
| Framework | Status | Evidence |
|---|---|---|
| ISO 27001 | โ Compliant | Architecture documentation, access control, vulnerability management |
| GDPR | โ Compliant | No PII collected, data protection by design |
| NIS2 | โ Compliant | Static site architecture, minimal attack surface, incident response |
| EU CRA | โ Aligned | SBOM generation, vulnerability disclosure, security updates |
Reference: GitHub Agentic Workflows Architecture โ the official specification for AW security layers, trust boundaries, and component isolation.
The EU Parliament Monitor implements GitHub Agentic Workflows (gh-aw v0.77.3) with a comprehensive defense-in-depth security architecture aligned to the official gh-aw 3-layer trust model. This architecture ensures that AI-driven news generation operates within strict security boundaries โ even if a compromised agent executes arbitrary code within its container, the layered isolation prevents unauthorized access or data exfiltration.
The gh-aw architecture implements three nested trust layers that provide independent, composable security guarantees:
| Layer | Trust Boundary | Enforcement | Threat Assumption |
|---|---|---|---|
| ๐ Layer 1: Substrate | Hardware โ kernel โ container runtime | GitHub Actions VM, Docker, iptables, MCP Gateway | Adversary fully controls user-level containers |
| ๐ Layer 2: Configuration | Declarative specifications + toolchain | Schema validation, SHA pinning, security scanners | Misconfiguration, overly permissive specs |
| ๐ Layer 3: Plan | Staged execution + output vetting | SafeOutputs, Threat Detection, stage boundaries | Incorrect plan construction, stage bypass |
Adversary Model: An adversary that may compromise untrusted user-level components (containers) and cause them to behave arbitrarily within granted privileges. The adversary may attempt to access other components' state, communicate over unintended channels, abuse legitimate channels for unintended actions, or confuse control logic.
Purpose: Memory isolation, CPU/resource isolation, kernel-enforced communication boundaries โ guarantees that hold even if an untrusted component is fully compromised.
The AWF containerizes the agent, binds it to a Docker network, and uses iptables to redirect HTTP/HTTPS traffic through a Squid proxy container with a configurable domain allowlist.
EU Parliament Monitor Allowlist (primary groups):
defaults, github, node, docker.io family*.europa.eu, ec.europa.eu, eur-lex.europa.eu, data.ecb.europa.eu and related EP sources*.imf.org (including api.imf.org)*.worldbank.org*.hack23.com, *.euparliamentmonitor.com and related project domainshost.docker.internal:8080 โ MCP Gateway (Docker bridge, local-only).github/workflows/shared/config/news-common-settings.mdAWF Architecture:
network.allowed listhost.docker.internal routes to MCP Gateway (Docker host alias)Security Guarantees:
MCP servers execute within isolated Docker containers, enforcing substrate-level separation between the agent and each server instance:
allowed: lists restrict available operations (unlisted tools blocked)gh-aw-mcpg container publishes host port 80 โ container port 8000, spawns isolated MCP server containers via Docker socket--cap-drop=ALL)ISMS Alignment: Secure Development Policy ยง Infrastructure Security
Purpose: Constrain which components are loaded, how they are connected, which communication channels are permitted, and what privileges are assigned โ validated before runtime.
Pinned Version: GH_AW_VERSION: v0.77.3 (enforced by compile-agentic-workflows.yml)
actions/checkout@sha # v4)actionlint (workflow linting + shellcheck), zizmor (privilege escalation), poutine (supply chain risks)Workflow Source Control:
.github/workflows/*.md (human-readable, version-controlled).github/workflows/*.lock.yml (deterministic, compiled).lock.yml files blocked by CODEOWNERS.md sources trigger recompilation via CIUser-generated content (issue titles, PR bodies, comments) is sanitized before being passed to the agent:
| Mechanism | Input โ Output | Protection |
|---|---|---|
| ๐ท๏ธ @mention Neutralization | @user โ `@user` |
Prevents unintended notifications |
| ๐ค Bot Trigger Protection | fixes #123 โ `fixes #123` |
Prevents automatic issue linking |
| ๐ XML/HTML Tag Conversion | <script> โ (script) |
Prevents injection via XML tags |
| ๐ URI Filtering | http://evil.com โ (redacted) |
Restricts to HTTPS from trusted domains |
| ๐ค Unicode Normalization | Homoglyphs โ Normalized | Prevents visual spoofing attacks |
| ๐ Content Limits | Large payloads โ Truncated | 0.5 MB max, 65k lines max |
| ๐ซ Control Character Removal | ANSI escapes โ Stripped | Removes terminal manipulation codes |
The MCP gateway intercepts tool calls and filters content based on author trust and merge status:
min-integrity: approved โ restricting content to owners, members, and collaboratorsmerged โ approved โ unapproved โ none (most โ least restrictive)Blocked shell patterns (prompt injection defense):
$() inside $(( )) arithmetic expansion${VAR:-$(cmd)} default-with-fallback command substitutioncommand + description fieldsISMS Alignment: Secure Development Policy ยง Change Management
Purpose: Constrain component behavior over time by decomposing workflows into stages with explicit inputs/outputs and mediated transitions. Important external side effects are explicit and undergo thorough vetting.
The SafeOutputs subsystem enforces permission separation โ the agent job never has direct write access to external state:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ค Agent Job โ โ ๐ Threat Detection Job โ โ โ
Safe Output Jobs โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโ โ
โ โข Read-only permissions โโโโโโถโ โข Download artifacts โโโโโโถโ โข create_pull_request โ
โ โข Buffered outputs only โ โ โข AI + custom analysis โ โ โข contents: write โ
โ โข agent_output.json โ โ โข Secret leak detection โ โ โข pull-requests: write โ
โ โข aw.patch (git diff) โ โ โข Malicious patch check โ โ โข Scoped permissions โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โข Policy violation scan โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โข Pass/Fail verdict โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
EU Parliament Monitor Safe-Output Limits:
news-translate.md: 10240 KB (14-language fan-out)excluded-files: analysis/**/data/** (prevents large EP API responses from overflowing patch limit)After the agent job completes, a separate detection job downloads buffered artifacts and analyzes them for threats:
Detection Checks:
Detection Properties:
Before workflow artifacts are uploaded, all files in /tmp/gh-aw are scanned and redacted:
secrets.* patternsif: always() even if workflow failsImmutable forensic trail of all tool invocations for post-incident analysis:
agent-stdio.log in workflow run artifactsgh aw logs (analyze runs), gh aw audit (investigate failures), gh aw status (health check)Logged Data:
Use Cases:
flowchart TB
subgraph Input["๐ฅ Input Layer"]
WF[/"๐ Workflow .md Source"/]
IMPORTS[/"๐ฆ Imports and Includes"/]
EVENT[/"โก GitHub Event<br/>Schedule / Manual Dispatch"/]
end
subgraph Compile["๐ Compilation-Time Security (Layer 2)"]
SCHEMA["๐ Schema Validation"]
EXPR["๐ Expression Safety Check"]
PIN["๐ Action SHA Pinning"]
SCAN["๐ Security Scanners<br/>actionlint + zizmor + poutine"]
end
subgraph Runtime["๐ก๏ธ Runtime Security (Layer 3)"]
PRE["๐ฆ Pre-Activation<br/>Role and Permission Checks"]
ACT["๐งน Activation<br/>Content Sanitization"]
AGENT["๐ค Agent Execution<br/>Read-Only Permissions"]
REDACT["๐ Secret Redaction"]
end
subgraph Isolation["๐ณ Isolation Layer (Layer 1)"]
AWF["๐ Agent Workflow Firewall<br/>Squid Proxy Egress Control"]
PROXY["๐ API Proxy<br/>Agent auth-token isolation"]
MCP["๐ฆ MCP Server Sandboxing<br/>Container Isolation"]
TOOL["๐ฏ Tool Allowlisting<br/>Explicit Permissions"]
end
subgraph OutputSec["๐ Output Security (Layer 3)"]
DETECT["๐ง Threat Detection<br/>AI-Powered Analysis"]
SAFE["โ
Safe Outputs<br/>Permission Separation"]
SANITIZE["๐งน Output Sanitization<br/>Content Validation"]
end
subgraph Result["โ Controlled Actions"]
PR["๐ Create Pull Request"]
end
WF --> SCHEMA
IMPORTS --> SCHEMA
SCHEMA --> EXPR
EXPR --> PIN
PIN --> SCAN
SCAN -->|".lock.yml"| PRE
EVENT --> ACT
PRE --> ACT
ACT --> AGENT
AGENT <--> AWF
AGENT <--> PROXY
AGENT <--> MCP
AGENT <--> TOOL
AGENT --> REDACT
REDACT --> DETECT
DETECT --> SAFE
SAFE --> SANITIZE
SANITIZE --> PR
flowchart TB
subgraph PreAct["๐ฆ Pre-Activation"]
ROLE["๐ค Role Permission Check"]
DEADLINE["โฐ Stop-After Deadline"]
SKIP["๐ Skip-If-Match Check"]
end
subgraph Activation["๐งน Activation"]
CONTEXT["๐ Prepare Workflow Context"]
SANITIZE2["๐ Sanitize Event Text"]
LOCK_CHECK["โ
Validate Lock File"]
end
subgraph AgentJob["๐ค Agent Job"]
CHECKOUT["๐ฅ Repository Checkout"]
NODE_SETUP["โ๏ธ Setup Node.js 26"]
MCP_START["๐ Start MCP Containers"]
PROMPT["๐ Generate Prompt"]
EXECUTE["๐ง Execute AI Engine"]
SECRET_REDACT["๐ Secret Redaction"]
UPLOAD["๐ค Upload Output Artifact"]
end
subgraph DetectJob["๐ Detection Job"]
DOWNLOAD["๐ฅ Download Artifact"]
ANALYZE["๐ง AI + Custom Analysis"]
VERDICT["โ๏ธ Security Verdict"]
end
subgraph SafeJobs["โ
Safe Output Jobs"]
CREATE_PR["๐ create_pull_request<br/>contents: write"]
end
ROLE --> DEADLINE --> SKIP
SKIP -->|"Pass"| CONTEXT
CONTEXT --> SANITIZE2 --> LOCK_CHECK
LOCK_CHECK --> CHECKOUT
CHECKOUT --> NODE_SETUP --> MCP_START --> PROMPT --> EXECUTE --> SECRET_REDACT --> UPLOAD
UPLOAD --> DOWNLOAD --> ANALYZE --> VERDICT
VERDICT -->|"Safe"| CREATE_PR
VERDICT -->|"Threat"| BLOCK["๐ซ Block All Outputs"]
| Layer | Mechanism | Protection Against | EU Parliament Monitor Implementation |
|---|---|---|---|
| ๐ Substrate | GitHub Actions runner (VM, kernel) | Memory corruption, privilege escalation | Ubuntu latest + Docker runtime |
| ๐ Substrate | Docker container runtime | Process isolation bypass, shared state | --cap-drop=ALL, resource limits |
| ๐ Substrate | AWF network controls (iptables + Squid) | Data exfiltration, unauthorized API calls | network.allowed 30+ entries (EU/IMF/WB/Hack23 + infra), default-deny |
| ๐ Substrate | MCP sandboxing (container isolation) | Container escape, unauthorized tools | EP/WB/IMF each in isolated containers |
| ๐ Configuration | Schema validation + expression allowlist | Invalid configs, unauthorized expressions | gh aw compile --validate |
| ๐ Configuration | Action SHA pinning | Supply chain attacks, tag hijacking | All actions pinned to commit SHA |
| ๐ Configuration | Security scanners | Privilege escalation, misconfigs | actionlint + zizmor + poutine |
| ๐ Configuration | Content sanitization | Prompt injection, bot triggers | @mention neutralization, URI filtering |
| ๐ Configuration | Integrity filtering | Untrusted content injection | min-integrity: approved (public repo) |
| ๐ Plan | SafeOutputs permission isolation | Unauthorized writes, state modification | Read-only agent โ vetted PR only |
| ๐ Plan | Threat detection pipeline | Secret leakage, malicious patches | AI detection + custom scanners |
| ๐ Plan | Secret redaction | Credential leakage in artifacts | Unconditional scan with if: always() |
| ๐ Plan | JSONL audit trail | Undetected compromise, forensics gaps | 90-day retention, gh aw logs/audit |
Defense-in-Depth Principle: Each layer provides independent security controls. Compromise of any single layer does not bypass the entire security model. Trust violations at the substrate level require vulnerabilities in the firewall, MCP Gateway, container runtime, kernel, hypervisor, or hardware.
ISMS Compliance:
The EU Parliament Monitor integrates with Model Context Protocol (MCP) servers to access European Parliament data, economic context (World Bank, IMF), and other external data sources. MCP gateway security ensures secure, resilient, and tamper-evident data access with drift-proofing controls.
Endpoint: EP_MCP_GATEWAY_URL=http://host.docker.internal:8080/mcp/european-parliament
Configuration source: scripts/mcp-setup.sh is sourced by every agentic workflow .md body. It resolves gateway.port and gateway.domain dynamically from /home/runner/.copilot/mcp-config.json (gh-aw writes these per-run) and falls back to host.docker.internal:8080 for non-agentic callers. Token extraction reads gateway.apiKey (legacy) or mcpServers['european-parliament'].headers.Authorization (raw API key) using node -e JSON parsing โ no jq dependency, no shell expansion of untrusted JSON values. Sets EP_MCP_GATEWAY_URL, EP_MCP_GATEWAY_API_KEY, and MCP_CLIENT_TIMEOUT_MS=180000 (180 s default).
Communication Model:
scripts/mcp-setup.sh (no jq dependency)src/mcp/ep-mcp-client.ts (compiled to scripts/mcp/ep-mcp-client.js)
EP_MCP_GATEWAY_URL and auth environment variables at runtimeSecurity Considerations:
host.docker.internal)Endpoint: https://dataservices.imf.org/REST/SDMX_3.0/
Communication Model:
fetch API)AbortController timeout enforced via IMF_API_TIMEOUT_MS environment variable (default 30 000 ms)Security Controls:
https://dataservices.imf.org/REST/SDMX_3.0/ base URL (configurable via IMF_API_BASE_URL)WAVE3_IMF_STRICT=false) or fails Stage-C (when strict mode is on)test/integration/mcp/imf-mcp.test.js exercise the client with an injected fetchImpl to cover success and failure pathsEndpoint: Configured via worldbank-mcp@1.0.1 npm package
Communication Model:
.github/copilot-mcp.jsonSecurity Controls:
package-lock.jsonworldbank-mcp for CVEsPurpose: Detect upstream MCP tool schema changes that could break workflows.
Implementation:
Canonical Tool Lists (exported from the MCP client modules):
IMF_MCP_TOOLS in src/mcp/imf-mcp-client.ts โ expected IMF economic data toolsWORLD_BANK_MCP_TOOLS in src/mcp/worldbank-mcp-client.ts โ expected World Bank data toolsEP_MCP_TOOLS export exists yet in src/mcp/ep-mcp-client.ts; see CRA-ASSESSMENT.md ยง5แต gap table row 13.)Integration Tests:
test/integration/mcp/imf-mcp.test.js asserts the expected IMF tool list matches IMF_MCP_TOOLStest/integration/mcp/worldbank-mcp.test.js asserts the expected World Bank tool list matches WORLD_BANK_MCP_TOOLStest/integration/mcp-integration.test.js (contract suite), pending a dedicated EP_MCP_TOOLS drift guardSemantic Versioning Enforcement:
Drift Detection Benefits:
Purpose: IMF as primary economic source under Wave-3 editorial policy with World Bank retained for non-economic resilience and pre-Wave-2 article back-compat.
Implementation:
Wave-3 strict (dark-launched) (articlePolicyHasIMFEconomicEvidence):
WAVE3_IMF_STRICT=true environment variable (parsed by isWave3IMFStrictEnabled)Wave-2 OR-gate (default) (articlePolicyHasEconomicContext):
Legacy soft-check (articlePolicyHasWorldBank):
Resilience Benefits:
WAVE3_IMF_STRICT is false (default), workflows still succeed on WB-only evidence for back-compatConfiguration File: .github/copilot-mcp.json
Purpose: Centralized registry of all MCP servers used by the project.
Change Management:
.github/copilot-mcp.json are Normal Changes under ISMS Change Management PolicyExample Configuration:
{
"mcpServers": {
"european-parliament": {
"command": "npx",
"args": ["-y", "european-parliament-mcp-server@1.3.20"],
"env": {
"EP_MCP_GATEWAY_URL": "http://host.docker.internal:8080/mcp/european-parliament"
}
},
"worldbank": {
"command": "npx",
"args": ["-y", "worldbank-mcp@1.0.1"]
}
}
}
ISMS Alignment:
| Document | Focus | Link |
|---|---|---|
| ๐ Security Architecture | Current State | This document |
| ๐ Future Security Architecture | Roadmap | FUTURE_SECURITY_ARCHITECTURE.md |
| โ๏ธ CI/CD Workflows | Current workflows | WORKFLOWS.md |
| ๐ Future Workflows | Planned enhancements | FUTURE_WORKFLOWS.md |
| ๐ Data Model | Data Structures | DATA_MODEL.md |
| ๐ Security Flow | Process Flows | FLOWCHART.md |
| ๐ Documentation Hub | Release documentation | docs/README.md |
| ๐ Release Process | Release procedures | docs/RELEASE_PROCESS.md |
| ๐ฏ Threat Model | Risk Analysis | #-threat-model |
| ๐ก๏ธ ISMS Secure Development | Policy Framework | ISMS-PUBLIC |
This security architecture implements controls aligned with Hack23 AB's publicly available ISMS framework. For complete policy mapping, see the Hack23 ISMS-PUBLIC repository.
| Policy Domain | Policy | Relevance to Architecture |
|---|---|---|
| ๐ Core Security | Information Security Policy | Overall security governance and framework |
| ๐ ๏ธ Development | Secure Development Policy | Security-integrated SDLC practices, CodeQL SAST scanning |
| ๐ Network | Network Security Policy | GitHub Pages CDN security, HTTPS enforcement |
| ๐ Cryptography | Cryptography Policy | TLS 1.3, HTTPS-only, Content Security Policy |
| ๐ Vulnerability | Vulnerability Management | Dependabot, CodeQL, npm audit, weekly scans |
| ๐จ Incident Response | Incident Response Plan | GitHub Security Advisories, coordinated disclosure |
| ๐ค Third-Party | Third Party Management | GitHub ecosystem assessment (GitHub Pages, Actions, npm) |
| ๐ Open Source | Open Source Policy | Apache-2.0 licensing, REUSE compliance, SBOM generation |
| ๐ Compliance | Compliance Checklist | ISO 27001, NIST CSF, CIS Controls alignment |
| ๐ท๏ธ Classification | Classification Framework | Public data classification (Level 1 confidentiality) |
| ๐ช๐บ CRA Compliance | CRA Conformity Assessment Process | CRA-ASSESSMENT.md self-assessment |
| ISMS Control Domain | Implementation Status | Notes |
|---|---|---|
| ๐ Access Control | โ Implemented | GitHub CODEOWNERS, branch protection, required reviews |
| ๐ Cryptography | โ Implemented | TLS 1.3, HTTPS-only, HSTS |
| ๐ Network Security | โ Implemented | GitHub Pages CDN, DDoS protection, edge caching |
| ๐ ๏ธ Secure Development | โ Implemented | CodeQL SAST, ESLint, TypeScript, Prettier, pre-commit hooks |
| ๐ Vulnerability Management | โ Implemented | Dependabot (weekly), CodeQL (push/PR), npm audit |
| ๐ Monitoring & Logging | โ ๏ธ Limited | GitHub Actions logs, CDN access logs (no backend logging) |
| ๐พ Data Protection | โ Implemented | No persistent storage, ephemeral build environment |
| ๐จ Incident Response | โ Documented | SECURITY.md, GitHub Security Advisories, 90-day disclosure |
The EU Parliament Monitor operates as a static content generation platform within the GitHub ecosystem, interfacing with the European Parliament MCP Server for data access.
graph TB
subgraph "External Actors"
User[๐ฅ EU Citizens & Researchers]
EP_API[๐๏ธ European Parliament<br/>Open Data API]
end
subgraph "GitHub Infrastructure"
GHA[โ๏ธ GitHub Actions<br/>Automated Workflows]
GHP[๐ GitHub Pages<br/>Static Hosting]
GH_SECURITY[๐ GitHub Security<br/>CodeQL, Dependabot, Secrets]
end
subgraph "EU Parliament Monitor"
EuPM[๐ฐ EU Parliament Monitor<br/>Static Website Generator]
EPMCP[๐ European Parliament<br/>MCP Server Client]
end
User -->|Browse News<br/>HTTPS| GHP
GHP -->|Serve Static<br/>HTML/CSS| User
GHA -->|Trigger Scheduled<br/>Weekday Crons| EuPM
GHA -->|Monitor Security| GH_SECURITY
EuPM -->|Connect via<br/>stdio/localhost| EPMCP
EPMCP -->|Query Parliamentary<br/>Data| EP_API
EP_API -->|Return JSON<br/>Public Data| EPMCP
EuPM -->|Generate<br/>Articles| GHP
GH_SECURITY -->|Scan Code<br/>Dependencies| EuPM
style User fill:#e1f5ff
style EP_API fill:#fff4e1
style GHA fill:#f0f0f0
style GHP fill:#f0f0f0
style GH_SECURITY fill:#ffe1e1
style EuPM fill:#e8f5e9
style EPMCP fill:#e8f5e9
8 Trust Boundaries enforce security zones:
flowchart LR
subgraph "Data Sources"
EP[European Parliament<br/>Open Data API]
end
subgraph "Processing"
MCP[MCP Server]
GEN[News Generator]
VAL[HTML Validator]
end
subgraph "Storage & Delivery"
GIT[Git Repository]
PAGES[GitHub Pages]
end
subgraph "Consumers"
USERS[End Users]
end
EP -->|Public JSON| MCP
MCP -->|Structured Data| GEN
GEN -->|HTML Articles| VAL
VAL -->|Validated HTML| GIT
GIT -->|Deploy| PAGES
PAGES -->|HTTPS| USERS
style EP fill:#fff4e1
style MCP fill:#e8f5e9
style GEN fill:#e8f5e9
style VAL fill:#e1f5ff
style GIT fill:#f0f0f0
style PAGES fill:#f0f0f0
style USERS fill:#e1f5ff
The system consists of stateless containers executing in GitHub Actions with no persistent infrastructure.
graph TB
subgraph "GitHub Actions Runner (Ubuntu Latest)"
subgraph "Article Generation Container"
CLI[๐ article-generator.ts<br/>TypeScript CLI (npm run generate-article)]
AGG[๐งฉ analysis-aggregator.ts<br/>Artifact Aggregator]
CLIENT[๐ ep-mcp-client.ts<br/>MCP Client Library]
end
subgraph "Index Generation Container"
IDX[๐ news-indexes.ts<br/>Index Generator]
end
subgraph "Sitemap Generation Container"
SITE[๐บ๏ธ sitemap.ts<br/>Sitemap + Political Intelligence Generator]
end
subgraph "European Parliament MCP Server"
MCP[๐๏ธ MCP Server Process<br/>stdio Communication]
end
subgraph "Validation Container"
HTML[โ
htmlhint<br/>HTML Validator]
LINT[๐ ESLint<br/>Code Quality]
TEST[๐งช Vitest<br/>Test Suite]
end
end
subgraph "GitHub Infrastructure"
REPO[๐ Git Repository<br/>news/, *.html, sitemap.xml]
PAGES[๐ GitHub Pages<br/>Static Hosting]
SECRETS[๐ GitHub Secrets<br/>Tokens, Variables]
end
subgraph "External Services"
EP_API[๐๏ธ European Parliament API<br/>data.europarl.europa.eu]
end
CLI -->|Initialize| CLIENT
CLIENT -->|Spawn Process| MCP
MCP -->|HTTPS| EP_API
EP_API -->|JSON Response| MCP
MCP -->|Structured Data| CLIENT
CLIENT -->|Parliamentary Data| CLI
CLI -->|Generate HTML| TEMPLATE
TEMPLATE -->|Write Files| REPO
IDX -->|Read Articles| REPO
IDX -->|Generate Indexes| REPO
SITE -->|Scan Files| REPO
SITE -->|Generate sitemap.xml| REPO
HTML -->|Validate| REPO
LINT -->|Check Quality| CLI
TEST -->|Run Tests| CLI
REPO -->|Deploy| PAGES
SECRETS -->|Provide Tokens| CLI
style CLI fill:#e8f5e9
style TEMPLATE fill:#e8f5e9
style CLIENT fill:#e8f5e9
style IDX fill:#e8f5e9
style SITE fill:#e8f5e9
style MCP fill:#fff4e1
style HTML fill:#e1f5ff
style LINT fill:#e1f5ff
style TEST fill:#e1f5ff
style REPO fill:#f0f0f0
style PAGES fill:#f0f0f0
style SECRETS fill:#ffe1e1
style EP_API fill:#fff4e1
| Container | Runtime | Privileges | Network Access | Persistence |
|---|---|---|---|---|
| News Generation | Node.js 26 | Read/Write repo | Localhost only | None (ephemeral) |
| Index Generation | Node.js 26 | Read/Write repo | None | None (ephemeral) |
| Sitemap Generation | Node.js 26 | Read/Write repo | None | None (ephemeral) |
| MCP Server | Node.js 26 | Read-only | HTTPS to EP API | None (ephemeral) |
| Validation | Node.js 26 | Read-only | None | None (ephemeral) |
Detailed component-level architecture showing internal structure and security boundaries.
graph TB
subgraph "News Generation Components"
direction TB
MAIN[Main CLI<br/>Command Parser]
LANG[Language Manager<br/>14 Languages]
TYPE[Article Type Manager<br/>5 Types]
subgraph "MCP Client Components"
CONN[Connection Manager<br/>Retry Logic]
REQ[Request Handler<br/>JSON-RPC 2.0]
RESP[Response Parser<br/>Data Validator]
end
subgraph "Template Components"
META[Metadata Generator<br/>SEO, Schema.org]
HTML[HTML Builder<br/>Sanitization]
CSS[Style Injector<br/>Inline CSS]
end
subgraph "Fallback Components"
CACHE[Content Cache<br/>Placeholder Data]
ERR[Error Handler<br/>Graceful Degradation]
end
end
subgraph "Validation Components"
HTMLV[HTML Validator<br/>htmlhint rules]
JSDOC[JSDoc Checker<br/>Documentation]
SECUR[Security Scanner<br/>eslint-plugin-security]
end
subgraph "Index Components"
SCAN[Article Scanner<br/>File Discovery]
PARSE[Metadata Parser<br/>Extract Info]
INDEX[Index Generator<br/>Multi-language]
end
subgraph "Sitemap Components"
CRAWLER[File Crawler<br/>Recursive Scan]
URL[URL Builder<br/>Canonical URLs]
XML[XML Generator<br/>Sitemap Protocol]
end
MAIN --> LANG
MAIN --> TYPE
LANG --> CONN
TYPE --> CONN
CONN --> REQ
REQ --> RESP
RESP --> META
RESP --> ERR
META --> HTML
HTML --> CSS
ERR --> CACHE
CACHE --> HTML
HTML --> HTMLV
CSS --> HTMLV
MAIN --> JSDOC
MAIN --> SECUR
SCAN --> PARSE
PARSE --> INDEX
CRAWLER --> URL
URL --> XML
style MAIN fill:#e8f5e9
style CONN fill:#fff4e1
style REQ fill:#fff4e1
style RESP fill:#fff4e1
style META fill:#e1f5ff
style HTML fill:#e1f5ff
style CSS fill:#e1f5ff
style CACHE fill:#f0f0f0
style ERR fill:#ffe1e1
style HTMLV fill:#e1f5ff
style JSDOC fill:#e1f5ff
style SECUR fill:#ffe1e1
| Component | Security Function | Controls |
|---|---|---|
| Connection Manager | MCP server connection security | Retry limits, timeout enforcement, error handling |
| Request Handler | JSON-RPC protocol integrity | Schema validation, request ID tracking |
| Response Parser | Input validation & sanitization | Data type checking, XSS prevention |
| HTML Builder | Output encoding | HTML entity encoding, CSP compliance |
| Error Handler | Fail-secure behavior | Fallback content, no sensitive data exposure |
| HTML Validator | Content integrity | htmlhint rules, standards compliance |
| Security Scanner | SAST detection | eslint-plugin-security, sonarjs rules |
flowchart TD
subgraph "GitHub Actions Identity"
WF[Workflow Trigger<br/>Schedule/Manual]
TOKEN[GITHUB_TOKEN<br/>Auto-generated]
PERMS[Permissions<br/>contents: write]
end
subgraph "Repository Operations"
READ[Read Repository<br/>Checkout Code]
WRITE[Write Changes<br/>Commit & Push]
end
subgraph "Security Boundaries"
SCOPE[Token Scope<br/>Repository Only]
EXPIRE[Token Expiry<br/>Job Duration]
end
WF -->|Provision| TOKEN
TOKEN -->|Grant| PERMS
PERMS -->|Allow| READ
PERMS -->|Allow| WRITE
TOKEN --> SCOPE
TOKEN --> EXPIRE
style WF fill:#f0f0f0
style TOKEN fill:#ffe1e1
style PERMS fill:#ffe1e1
style READ fill:#e8f5e9
style WRITE fill:#e8f5e9
style SCOPE fill:#e1f5ff
style EXPIRE fill:#e1f5ff
Controls:
contents: write only, no admin/secrets accessISMS Alignment:
Control Implementation:
Security Rationale:
flowchart TD
subgraph "External Data Sources"
EP[European Parliament API<br/>Untrusted Input]
end
subgraph "Validation Pipeline"
SCHEMA[Schema Validation<br/>JSON Structure Check]
TYPE[Type Validation<br/>Data Type Enforcement]
RANGE[Range Validation<br/>Bounds Checking]
end
subgraph "Sanitization Pipeline"
HTML_STRIP[HTML Tag Stripping<br/>Remove Dangerous Tags]
ENTITY[Entity Encoding<br/>HTML Special Chars]
SCRIPT[Script Removal<br/>XSS Prevention]
end
subgraph "Output Generation"
SAFE[Safe HTML<br/>Validated Content]
end
EP -->|Raw JSON| SCHEMA
SCHEMA -->|Valid| TYPE
SCHEMA -->|Invalid| ERR[Log Error &<br/>Use Fallback]
TYPE -->|Valid| RANGE
TYPE -->|Invalid| ERR
RANGE -->|Valid| HTML_STRIP
RANGE -->|Invalid| ERR
HTML_STRIP --> ENTITY
ENTITY --> SCRIPT
SCRIPT --> SAFE
style EP fill:#fff4e1
style SCHEMA fill:#e1f5ff
style TYPE fill:#e1f5ff
style RANGE fill:#e1f5ff
style HTML_STRIP fill:#ffe1e1
style ENTITY fill:#ffe1e1
style SCRIPT fill:#ffe1e1
style SAFE fill:#e8f5e9
style ERR fill:#f0f0f0
Validation Controls:
Sanitization Controls:
<, >, &, ", ' to entities<script> tags from inputonclick, onerror, etc.ISMS Alignment:
The TypeScript generation layer in src/generators/shared/ implements a phantom-brand type system that turns sanitisation contracts into compile-time guarantees. The branded types are erased by TypeScript (zero runtime cost) but prevent accidental interpolation of unsanitised strings into HTML, XML, or URL contexts.
| Branded Type | Producer Function | Source Module | Guarantee |
|---|---|---|---|
SafeHtmlString |
toSafeHtml(raw) |
src/generators/shared/html-escape.ts |
HTML-entity-escaped (&, <, >, ", ') โ safe for HTML interpolation |
SafeXmlString |
toSafeXml(raw) |
src/generators/shared/html-escape.ts |
XML-entity-escaped โ safe for sitemap.xml / rss.xml interpolation |
AbsoluteUrl |
toAbsoluteUrl(raw) |
src/generators/shared/html-escape.ts |
Validated https:// URL with attribute-safe character set |
RelativeFilePath |
toRelativeFilePath() |
src/generators/shared/html-escape.ts |
POSIX-normalised, no leading slash, no .. traversal |
Compile-time enforcement model:
flowchart LR
RAW[raw: string<br/>untrusted MCP / EP / IMF input]
PROD[Producer Function<br/>toSafeHtml / toSafeXml /<br/>toAbsoluteUrl / toRelativeFilePath]
BRANDED[SafeHtmlString /<br/>SafeXmlString /<br/>AbsoluteUrl /<br/>RelativeFilePath]
TPL[HTML / XML Template<br/>accepts only branded types]
OUT[Generated artefact<br/>provably escaped at compile time]
RAW -->|"escapeHTML / escapeXML /<br/>URL validation"| PROD
PROD -->|"phantom brand:<br/>{readonly [__brand]: 'SafeHtml'}"| BRANDED
BRANDED -->|"type-checked interpolation"| TPL
TPL --> OUT
BLOCK[โ raw string passed<br/>directly to template] -.->|"TS2322:<br/>Type 'string' is not<br/>assignable to 'SafeHtmlString'"| TPL
style RAW fill:#fff4e1
style PROD fill:#e1f5ff
style BRANDED fill:#e8f5e9
style TPL fill:#e8f5e9
style OUT fill:#e8f5e9
style BLOCK fill:#ffe1e1
Security properties:
__brand symbol). They impose zero performance overhead on generated output.html-escape.ts is the only module that produces branded values. Every template parameter typed SafeHtmlString is provably escaped because it can only originate from toSafeHtml().string directly into a template that accepts SafeHtmlString is a TypeScript error (TS2322). The build fails before the artefact reaches CI.dangerouslySetInnerHTML equivalent โ the project ships no escape hatch that bypasses the brand. markdown-it runs with html: false and the result is post-processed by src/utils/html-sanitize.ts before being branded.Verification:
test/unit/generators/shared/html-escape.test.js exercise each producer with hostile inputs (<script>, javascript:, RTL override characters, attribute-breakout payloads).test/integration/html-article-pipeline.test.js verify the pipeline-level invariant: every generated HTML page passes HTMLHint, contains no inline <script>, and has CSP-compliant output across all 14 languages.src/generators/shared/index.ts re-exports only the producers; the brand symbol itself is module-private, preventing user code from forging branded values.ISMS Alignment:
GitHub Agentic Workflows execute AI-authored bash inside a sandboxed runner. To prevent prompt-injection-driven arbitrary code execution, the platform's shell-safety filter rejects a defined set of bash expansion patterns. Repository code, prompts, and helper scripts must avoid these patterns or the run fails โ sometimes after burning the 60-minute workflow budget. The repository enforces this at three layers:
Layer 1 โ Forbidden expansion patterns (matched by test/unit/shell-safety.test.js against every scripts/**.sh):
| Pattern | Example (DO NOT USE) | Risk |
|---|---|---|
| Nested parameter expansion | ${var#${other}}, ${A:-${B:-}} |
Inner expansion result becomes part of outer pattern |
| Indirect expansion | ${!var}, ${!prefix*} |
Reads arbitrary variables by name |
| Parameter transformation | ${var@P}, ${var@Q}, ${var@E} |
@P re-evaluates the string as a prompt |
| Nested command substitution | $(cmd $(inner)) |
Inner $() executes under the outer |
| Default-with-command-substitution | ${VAR:-$(cmd)} |
Default expression is a live command |
Input redirection inside $() |
$(cmd < file) |
Smuggles arbitrary file reads into substitutions |
eval |
eval "$str" |
Explicit arbitrary-code execution |
Adjacent ${RANDOM}${RANDOM} |
suffix="${RANDOM}${RANDOM}" |
Adjacency heuristic trips nested-expansion detection |
Layer 2 โ Drift-guard test (test/unit/shell-safety.test.js):
scripts/**.sh file.github/prompts/00-scope-and-ground-rules.md ยง47 and .github/prompts/08-infrastructure.md ยง177-181npm run test Vitest suite โ every PR is gated on itLayer 3 โ Prompt-level rules (read by every news-generation agent):
.github/prompts/00-scope-and-ground-rules.md ยง47 โ authoritative short-form forbidden-pattern list, imported by every news-<type>.md workflow body.github/prompts/08-infrastructure.md ยง177-181 โ long-form explanations with safe replacement idioms (e.g. if/elif/else instead of ${A:-${B:-}}, two-step variable assignment instead of nested $()).github/prompts/02-analysis-protocol.md ยง10 โ mandates that bash in agentic workflows delegates to repo-hosted, pre-audited helpers (e.g. scripts/checkpoint-analysis-to-memory.sh) rather than inlining expansion-heavy commandsThreat model linkage: see THREAT_MODEL.md Threat T-029 (Shell Expansion Injection in Agentic Workflows) for the STRIDE / MITRE ATT&CK mapping and residual risk rating.
ISMS Alignment:
| Data Type | Classification | Storage | Encryption | Retention |
|---|---|---|---|---|
| News Articles | Public | Git repository | At-rest (GitHub) | Indefinite |
| EP API Responses | Public | Ephemeral (runtime only) | In-transit (TLS 1.3) | None |
| Generation Metadata | Public | Git repository | At-rest (GitHub) | Indefinite |
| GitHub Tokens | Secret | GitHub Secrets | Encrypted | Auto-rotate |
| MCP Communication | Internal | Localhost only | N/A (local) | None |
ISMS Alignment:
Control Implementation:
GDPR Compliance:
Cryptographic Key Lifecycle:
As a static site generator, EU Parliament Monitor has a minimal key management footprint:
| Key Type | Purpose | Management | Rotation |
|---|---|---|---|
| GitHub Actions GITHUB_TOKEN | CI/CD authentication | Auto-generated per job | Per-workflow run (ephemeral) |
| MCP PAT | EP MCP Server access | GitHub Secrets (encrypted at rest) | Manual rotation, 90-day recommended |
| TLS Certificates | HTTPS for GitHub Pages | GitHub-managed (Let's Encrypt) | Auto-renewed every 90 days |
| GPG Signing Keys | Commit verification | Developer-managed | Per policy, minimum 2048-bit RSA |
Key Security Controls:
permissions: block)ISMS Alignment:
graph TB
subgraph "External Network"
direction TB
USERS[๐ Internet Users<br/>Public Access]
EP_NET[๐๏ธ European Parliament<br/>data.europarl.europa.eu]
end
subgraph "GitHub Infrastructure"
direction TB
GH_CDN[๐ GitHub Pages CDN<br/>HTTPS Only]
GH_RUNNER[โ๏ธ GitHub Actions Runner<br/>Ephemeral VM]
end
subgraph "Application Layer"
direction TB
STATIC[๐ Static HTML/CSS<br/>Read-Only Files]
MCP[๐ MCP Server<br/>localhost:random_port]
end
USERS -->|HTTPS 443<br/>TLS 1.3| GH_CDN
GH_CDN -->|Serve| STATIC
GH_RUNNER -->|HTTPS 443<br/>TLS 1.3| EP_NET
GH_RUNNER -->|localhost<br/>stdio/pipe| MCP
MCP -->|HTTPS 443| EP_NET
style USERS fill:#e1f5ff
style EP_NET fill:#fff4e1
style GH_CDN fill:#f0f0f0
style GH_RUNNER fill:#f0f0f0
style STATIC fill:#e8f5e9
style MCP fill:#e8f5e9
Network Security Controls:
HTTPS Enforcement
max-age=31536000Localhost-Only MCP Communication
No Exposed Ports
Outbound Restrictions
ISMS Alignment:
Current Security Headers (GitHub Pages Defaults):
GitHub Pages provides the following default security headers:
X-Content-Type-Options: nosniff - Prevent MIME sniffingHTML Meta Tags (Implemented):
The generated HTML pages include no inline JavaScript and no external scripts, which provides inherent XSS protection. A Content-Security-Policy meta tag is also emitted in every generated article page.
Implemented Security Meta Tags:
Content-Security-Policy - Emitted in every article page via src/aggregator/article-html.ts as a <meta http-equiv> tag (not a CloudFront response-headers policy):<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self'; connect-src 'self'; frame-src 'none'; base-uri 'self'; form-action 'none'">
X-Content-Type-Options: nosniff - Emitted in every article page (meta tag)Referrer-Policy: no-referrer - Emitted in every article page (meta tag)X-Frame-Options - Relies on GitHub Pages / CloudFront defaults (no meta-tag equivalent)Policy decisions:
script-src 'self' โ no inline <script> blocks in generated HTML; all executable JS is externalised to js/index-runtime.js (index pages) and js/article-runtime.js (article pages). JSON-LD blocks use type="application/ld+json" which is non-executable and exempt from script-src.style-src 'self' 'unsafe-inline' โ required for existing inline style attributes in article content (Chart.js containers, CSS variables)img-src 'self' https: data: โ permits EU Parliament remote images and data URIsconnect-src 'self' โ permits same-origin fetch/XHR (Chart.js data, runtime JS); no third-party network calls allowed at runtimeframe-src 'none', form-action 'none', base-uri 'self' โ hard deny on embedding and form posts; restrict base URLCSP Delivery Mechanism:
CSP is delivered per-page via <meta http-equiv> rather than via CloudFront response headers, so the policy ships with the generated HTML and applies identically whether the site is served from AWS S3+CloudFront (primary) or GitHub Pages (fallback). Additional hardening headers (HSTS, Strict-Transport-Security, X-Content-Type-Options: nosniff, Permissions-Policy) are applied at the CloudFront edge as defence-in-depth; evaluating a CloudFront response-headers policy that duplicates the CSP is tracked as CRA-ASSESSMENT.md ยง5แต gap table row 9.
HTML Sanitization: src/utils/html-sanitize.ts sanitizes all MCP-derived strings before HTML emission
Privacy: No cookies; localStorage limited to theme preference (non-PII)
Multi-Layer XSS Defense:
flowchart TD
INPUT[EP API Data /<br/>External Input]
subgraph "Defense Layer 1: Input Validation"
VAL[Schema Validation]
TYPE[Type Checking]
end
subgraph "Defense Layer 2: Sanitization"
STRIP[HTML Tag Stripping]
ENCODE[Entity Encoding]
end
subgraph "Defense Layer 3: Output Encoding"
HTML_ENCODE[HTML Context Encoding]
ATTR_ENCODE[Attribute Encoding]
end
subgraph "Defense Layer 4: CSP"
CSP[Content Security Policy]
META[CSP Meta Tags]
end
OUTPUT[Safe HTML Output]
INPUT --> VAL
VAL --> TYPE
TYPE --> STRIP
STRIP --> ENCODE
ENCODE --> HTML_ENCODE
HTML_ENCODE --> ATTR_ENCODE
ATTR_ENCODE --> CSP
CSP --> META
META --> OUTPUT
style INPUT fill:#fff4e1
style VAL fill:#e1f5ff
style TYPE fill:#e1f5ff
style STRIP fill:#ffe1e1
style ENCODE fill:#ffe1e1
style HTML_ENCODE fill:#ffe1e1
style ATTR_ENCODE fill:#ffe1e1
style CSP fill:#e8f5e9
style META fill:#e8f5e9
style OUTPUT fill:#e8f5e9
XSS Controls:
<script>, <iframe>, etc.)escapeHTML() in src/utils/file-utils.tsisSafeURL() validates URL schemes (http/https only)Testing:
Supply Chain Security Controls:
graph TB
subgraph "Dependency Management"
PKG[package.json<br/>29 Dependencies]
LOCK[package-lock.json<br/>Locked Versions]
end
subgraph "Automated Scanning"
DEP[Dependabot<br/>Weekly Scans]
AUDIT[npm audit<br/>CI Checks]
CODEQL[CodeQL<br/>SAST]
end
subgraph "Update Process"
PR[Auto PR<br/>Version Updates]
TEST[CI Tests<br/>Validation]
MERGE[Merge<br/>After Review]
end
subgraph "Enforcement"
FAIL[Block PR<br/>on Vulnerabilities]
BADGE[Security Badge<br/>Status]
end
PKG --> LOCK
LOCK --> DEP
LOCK --> AUDIT
LOCK --> CODEQL
DEP --> PR
AUDIT --> FAIL
PR --> TEST
TEST --> MERGE
CODEQL --> FAIL
MERGE --> BADGE
style PKG fill:#e8f5e9
style LOCK fill:#e8f5e9
style DEP fill:#e1f5ff
style AUDIT fill:#e1f5ff
style CODEQL fill:#ffe1e1
style PR fill:#f0f0f0
style TEST fill:#e1f5ff
style MERGE fill:#e8f5e9
style FAIL fill:#ffe1e1
style BADGE fill:#e8f5e9
Dependency Security:
.github/workflows/deploy-s3.yml uses OIDC (no long-lived AWS keys)npm run copy-vendor with SRI (no CDN risk)codeql.yml, dependency-review.yml, scorecards.yml, reuse.yml (SPDX via REUSE.toml)Current Dependencies:
ISMS Alignment:
Workflow Security Controls:
flowchart TD
subgraph "Workflow Trigger"
SCHED[Schedule Trigger<br/>Weekday Crons]
MANUAL[Manual Trigger<br/>workflow_dispatch]
end
subgraph "Security Checks"
PIN[SHA-Pinned Actions<br/>Supply Chain]
PERM[Minimal Permissions<br/>contents: write]
RUNNER[GitHub-Hosted Runner<br/>Ephemeral]
end
subgraph "Execution"
CHECKOUT[Checkout Code]
INSTALL[npm ci<br/>Reproducible Build]
GENERATE[Generate News]
VALIDATE[Validate HTML]
end
subgraph "Security Scans"
AUDIT[npm audit<br/>Vulnerability Check]
CODEQL_SCAN[CodeQL<br/>SAST]
LINT[ESLint Security<br/>Code Quality]
end
subgraph "Commit"
COMMIT[Commit Changes<br/>Automated]
PUSH[Push to GitHub]
end
SCHED --> PIN
MANUAL --> PIN
PIN --> PERM
PERM --> RUNNER
RUNNER --> CHECKOUT
CHECKOUT --> INSTALL
INSTALL --> AUDIT
AUDIT --> GENERATE
GENERATE --> VALIDATE
VALIDATE --> LINT
LINT --> CODEQL_SCAN
CODEQL_SCAN --> COMMIT
COMMIT --> PUSH
style SCHED fill:#f0f0f0
style MANUAL fill:#f0f0f0
style PIN fill:#ffe1e1
style PERM fill:#ffe1e1
style RUNNER fill:#e1f5ff
style AUDIT fill:#ffe1e1
style CODEQL_SCAN fill:#ffe1e1
style LINT fill:#e1f5ff
style COMMIT fill:#e8f5e9
style PUSH fill:#e8f5e9
Infrastructure Controls:
Ephemeral Runners
Secrets Management
Workflow Permissions
contents: write - Repository read/write onlySupply Chain Security
Workflow Hardening (StepSecurity Harden Runner)
step-security/harden-runner deployed across all CI/CD workflowsaudit mode (monitors outbound network calls)block mode on deployment workflows (only allowed
endpoints)ISMS Alignment:
Hosting Security:
Math.random() banned by ESLintStatic Site Security:
Purpose: Prevent AI-generated content leakage of placeholder templates and ensure production-quality intelligence output.
2-Pass Validator: validate-analysis-completeness.js scans rendered HTML for:
FALLBACK_TEMPLATE_PATTERNS: Detects template placeholder leaksAI_MARKER sentinels: Zero-tolerance for [AI_ANALYSIS_REQUIRED] markersAPIs:
scanHtmlForFallbackLeaks(htmlContent): Scan single HTML stringscanArticleHtmlFiles(directory): Scan all generated articlesPre-Translation Gate: news-translate.md scans English sources before 14-language fan-out to block bad content propagation
Quality Thresholds (from analysis/methodologies/reference-quality-thresholds.json):
intelligence/mcp-reliability-audit.md โฅ200 words (breaking โฅ385)intelligence/reference-analysis-quality.md โฅ140 words (breaking โฅ190)Zero-Tolerance Enforcement:
[AI_ANALYSIS_REQUIRED] sentinel presencePrompt Injection Defense:
src/utils/html-sanitize.tsISMS Alignment: AI Policy โ AI content quality assurance
The 15 news generation workflows (breaking, week-ahead, week-in-review, month-ahead, month-in-review, quarter-ahead, quarter-in-review, year-ahead, year-in-review, term-outlook, election-cycle, committee-reports, motions, propositions, news-translate) use the GitHub Agentic Workflows (gh-aw) framework with built-in security controls:
Workflow Hardening:
timeout-minutes: 45 hard stop prevents runaway
executiondata.europarl.europa.eu, *.europa.eu, github.com, and required
infrastructure endpoints via safe-outputs configurationnews/{type}-{date} pattern (e.g.,
news/week-ahead-2026-02-23) prevents branch conflictsconcurrency: gh-aw-${{ github.workflow }}
prevents parallel execution of the same workflowpermissions: {} at workflow level,
elevated only where neededMCP Data Resilience:
EU Parliament Monitor ensures data integrity throughout its news generation pipeline, from European Parliament source data through to published content. As a static site generator operating on public parliamentary data, integrity controls focus on content accuracy, tamper-evident change tracking, and build reproducibility.
flowchart TD
subgraph "Data Integrity Architecture"
direction TB
EP[๐๏ธ EP Open Data API] -->|HTTPS/TLS 1.3| VALIDATE[๐ Input Validation<br/>Schema + Type + Range]
VALIDATE -->|Valid Data| TRANSFORM[๐ Content Transform<br/>Multi-language Generation]
VALIDATE -->|Invalid| REJECT[โ ๏ธ Reject & Log<br/>Fallback to Cached]
TRANSFORM -->|HTML Output| SANITIZE[๐ก๏ธ HTML Sanitization<br/>XSS Prevention]
SANITIZE -->|Safe Content| COMMIT[๐ Git Commit<br/>Immutable History]
COMMIT -->|SHA Verified| DEPLOY[๐ GitHub Pages<br/>CDN Distribution]
end
subgraph "Audit Trail"
direction TB
GIT_LOG[๐ Git Log<br/>Immutable Audit Trail]
GHA_LOG[๐ GitHub Actions Logs<br/>90-day Retention]
CODEQL[๐ CodeQL Findings<br/>SAST Audit]
DEP_AUDIT[๐ฆ Dependency Audit<br/>npm audit History]
end
COMMIT --> GIT_LOG
COMMIT --> GHA_LOG
style EP fill:#fff4e1
style VALIDATE fill:#e1f5ff
style SANITIZE fill:#ffe1e1
style COMMIT fill:#e8f5e9
style DEPLOY fill:#e8f5e9
| Control | Implementation | Evidence |
|---|---|---|
| Immutable Commit History | Git SHA-256 hash chain, signed commits via GPG | Every content change has traceable commit |
| Branch Protection | Required reviews, status checks, no force pushes | Main branch protected against unauthorized changes |
| Build Provenance | GitHub Actions workflow logs with SLSA Level 3 | Reproducible builds with attestation |
| Content Checksums | Generated HTML has deterministic output from same inputs | Build reproducibility verification |
| Dependency Lock | package-lock.json ensures reproducible installs |
npm ci for deterministic dependency resolution |
ISMS Alignment:
EU Parliament Monitor, as a static website generator, implements tracking mechanisms appropriate for its architectureโfocusing on build-time operations and privacy-respecting analytics. There are no user sessions, cookies, or client-side tracking.
flowchart TD
subgraph "Build Session Tracking"
direction TB
A[โฐ GitHub Actions Trigger] -->|"Daily Cron"| B[๐ Workflow Run]
B -->|"Create"| C[๐ Build Session]
B -->|"Execute"| D[๐ ๏ธ Build Steps]
D -->|"Generate"| E[๐ Build Events]
E -->|"Associated with"| C
C -->|"Contains"| F[๐ Session Metadata]
F -->|"Records"| G[๐ Run ID]
F -->|"Records"| H[๐ค Actor/Trigger]
F -->|"Records"| I[๐ฟ Branch/Commit]
F -->|"Records"| J[โฐ Timestamps]
E -->|"Contains"| K[๐ Event Metadata]
K -->|"Records"| L[๐ Operation Type]
K -->|"Records"| M[๐ Step Name]
K -->|"Records"| N[โ
Success/Failure]
K -->|"Records"| O[โฑ๏ธ Duration]
C & E -->|"Store"| P[๐พ GitHub Actions Logs]
P -->|"Analysis"| Q[๐ Workflow Insights]
P -->|"Audit"| R[๐ Security Review]
end
style A fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style B fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style C,E fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
style D fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style F,K fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style G,H,I,J,L,M,N,O fill:#00E676,stroke:#00C853,stroke-width:2px,color:black,font-weight:bold
style P fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style Q,R fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
classDef default font-weight:bold
Every workflow execution creates a tracked session with comprehensive metadata:
Build Session Metadata:
GITHUB_RUN_IDGITHUB_ACTOR and
GITHUB_TRIGGERING_ACTORGITHUB_REF), commit SHA (GITHUB_SHA)Implementation:
# .github/workflows/news-breaking.lock.yml (compiled from news-breaking.md)
env:
RUN_ID: ${{ github.run_id }}
ACTOR: ${{ github.actor }}
COMMIT_SHA: ${{ github.sha }}
BRANCH: ${{ github.ref_name }}
Every build step generates trackable events:
Build Event Metadata:
Key Build Events Tracked:
Approach: No client-side tracking (no JavaScript analytics), privacy-first
Analytics Sources:
GitHub Pages CDN Logs (limited access):
Repository Insights:
Privacy Protections:
GitHub Actions Logs:
Security Benefits:
EU Parliament Monitor implements security event monitoring appropriate for a static site generator, focusing on build-time security events and dependency vulnerabilities.
flowchart TD
subgraph "Security Event Monitoring"
direction TB
A[๐ก๏ธ GitHub Security<br>Events] --> B[โ
Workflow Success]
A --> C[โ ๏ธ Workflow Failure]
D[๐ Dependency<br>Security] --> E[๐จ Dependabot Alert]
D --> F[๐ Automated PR]
G[๐ Code<br>Scanning] --> H[๐ CodeQL Analysis]
G --> I[โ ๏ธ Security Finding]
B & C & E & F & H & I -->|"Generate"| J[๐ Security Event]
J -->|"Contains"| K[๐ Event Metadata]
K -->|"Records"| L[๐ Event Type]
K -->|"Records"| M[โก Severity]
K -->|"Records"| N[๐ Affected Component]
K -->|"Records"| O[โฑ๏ธ Timestamp]
J -->|"Triggers"| P[๐จ Notification]
P -->|"If Critical"| Q[๐ฅ Security Team Alert]
J -->|"Store"| R[๐พ GitHub Security]
R -->|"Dashboard"| S[๐ Security Overview]
R -->|"Compliance"| T[๐ Audit Reports]
end
style A,D,G fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style B fill:#00E676,stroke:#00C853,stroke-width:2px,color:black,font-weight:bold
style C,E,I fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
style F,H fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style J fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style K,P fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style L,M,N,O fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style Q fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
style R fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style S,T fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
classDef default font-weight:bold
Our system monitors several categories of security events:
Workflow Execution Events:
Authentication Events:
Implementation:
# .github/workflows/news-breaking.lock.yml (example โ all news-*.lock.yml follow this pattern)
- name: Monitor Build Security
if: failure()
run: |
echo "::warning::Build failed - security review required"
echo "Actor: ${{ github.actor }}"
echo "Commit: ${{ github.sha }}"
Dependabot Alerts:
Automated Response:
Monitoring:
# npm audit in CI/CD pipeline
npm audit --audit-level=moderate
CodeQL Analysis:
main, every pull requestAlert Handling:
Implementation:
# .github/workflows/codeql.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: '/language:javascript'
Deployment Security:
Health Checks:
GitHub Security Dashboard:
Notification Channels:
Response SLAs:
GitHub Actions Logs:
Security Alert History:
EU Parliament Monitor implements a comprehensive vulnerability management program covering code, dependencies, infrastructure, and content delivery.
flowchart TD
subgraph "Vulnerability Detection"
direction TB
CODEQL[๐ CodeQL SAST<br/>Push & PR Scans]
DEPBOT[๐ค Dependabot<br/>Weekly Scans]
NPM_AUDIT[๐ฆ npm audit<br/>CI/CD Pipeline]
SECRET[๐ Secret Scanning<br/>Continuous]
ESLINT[๐ ESLint Security<br/>Pre-commit]
end
subgraph "Triage & Prioritization"
direction TB
CVSS[๐ CVSS Scoring]
SLA[โฑ๏ธ SLA Assignment]
ASSIGN[๐ค Owner Assignment]
end
subgraph "Remediation"
direction TB
PATCH[๐ง Apply Patch]
TEST[๐งช Test Fix]
DEPLOY[๐ Deploy]
VERIFY[โ
Verify]
end
CODEQL --> CVSS
DEPBOT --> CVSS
NPM_AUDIT --> CVSS
SECRET --> CVSS
ESLINT --> CVSS
CVSS --> SLA --> ASSIGN
ASSIGN --> PATCH --> TEST --> DEPLOY --> VERIFY
style CODEQL fill:#e1f5ff
style DEPBOT fill:#e1f5ff
style NPM_AUDIT fill:#e1f5ff
style CVSS fill:#fff4e1
style VERIFY fill:#e8f5e9
| Severity | CVSS Range | Response Time | Resolution Time | Escalation |
|---|---|---|---|---|
| ๐ด Critical | 9.0-10.0 | 4 hours | 24 hours | Immediate CEO notification |
| ๐ High | 7.0-8.9 | 24 hours | 7 days | Weekly security review |
| ๐ก Medium | 4.0-6.9 | 48 hours | 30 days | Monthly maintenance |
| ๐ข Low | 0.1-3.9 | 7 days | 90 days | Quarterly update |
| Scanner | Trigger | Frequency | Coverage |
|---|---|---|---|
| CodeQL | Push to main, PR | Per-commit | JavaScript/TypeScript SAST |
| Dependabot | Scheduled | Weekly (Monday) | npm ecosystem |
| npm audit | CI pipeline | Every build | Direct + transitive deps |
| Secret Scanning | Push | Continuous | All committed content |
| ESLint Security | Pre-commit | Every commit | Code quality + security rules |
| REUSE | CI pipeline | Every build | License compliance |
ISMS Alignment:
EU Parliament Monitor manages configuration as code, ensuring all infrastructure and application settings are version-controlled, reviewed, and auditable.
| Configuration | Source of Truth | Validation | Change Process |
|---|---|---|---|
| GitHub Actions Workflows | .github/workflows/*.yml |
YAML lint, action SHA pinning | PR review + required checks |
| TypeScript Configuration | tsconfig.json (strict mode) |
tsc --noEmit type checking |
PR review |
| ESLint Rules | eslint.config.js |
npm run lint |
PR review |
| Dependabot Config | .github/dependabot.yml |
GitHub validation | PR review |
| Content Security Policy | article-html.ts |
E2E tests verify CSP headers | PR review + automated tests |
| Branch Protection | GitHub Repository Settings | GitHub API audit | Admin-only changes |
| MCP Server Config | .github/copilot-mcp.json |
Schema validation | PR review |
package-lock.json prevents dependency driftstrict: true with all additional strict checks enabled| Framework | Automated Check | Frequency | Evidence |
|---|---|---|---|
| REUSE (SPDX) | reuse lint in CI |
Every build | License compliance |
| OpenSSF Scorecard | GitHub-integrated | Weekly | Supply chain security |
| SLSA | GitHub attestation | Per-release | Build provenance |
| HTMLHint | npm run htmlhint |
Every build | Content standards |
| TypeScript Strict | tsc --noEmit |
Every build | Type safety |
| Prettier | npm run format:check |
Every build | Code consistency |
ISMS Alignment:
EU Parliament Monitor collects security metrics and monitoring data appropriate for its static site architecture, focusing on build-time security events and supply chain monitoring.
flowchart LR
subgraph "Data Sources"
GHA[๐ GitHub Actions<br/>Build Metrics]
CODEQL_M[๐ CodeQL<br/>Finding Trends]
DEP_M[๐ฆ Dependabot<br/>Alert Metrics]
AUDIT_M[๐ npm audit<br/>Vulnerability Count]
end
subgraph "Metrics Dashboard"
KPI[๐ Security KPIs]
TREND[๐ Trend Analysis]
SLA_M[โฑ๏ธ SLA Compliance]
end
GHA --> KPI
CODEQL_M --> KPI
DEP_M --> KPI
AUDIT_M --> KPI
KPI --> TREND
KPI --> SLA_M
style KPI fill:#e8f5e9
style TREND fill:#e1f5ff
| Metric | Target | Measurement | Current |
|---|---|---|---|
| Mean Time to Detect (MTTD) | < 1 hour | Automated scanning detection | โ Real-time (CI/CD) |
| Mean Time to Remediate (MTTR) | < 48 hours (high) | Alert to fix merge | โ < 48 hours |
| Vulnerability Backlog | 0 critical/high | Open findings count | โ 0 |
| Dependency Currency | < 30 days behind | Package age analysis | โ Weekly updates |
| Build Success Rate | > 95% | CI/CD pipeline metrics | โ > 98% |
| Security Test Coverage | > 80% line | Vitest coverage report | โ 82%+ |
| SAST False Positive Rate | < 10% | CodeQL triage ratio | โ < 5% |
ISMS Alignment:
EU Parliament Monitor's static architecture inherently provides high availability through GitHub Pages' globally distributed CDN infrastructure.
graph TD
subgraph "GitHub Pages Global CDN"
A[๐ Global CDN] --> B[๐ Edge Locations<br>Worldwide]
B --> C[๐ช๐บ Europe]
B --> D[๐บ๐ธ Americas]
B --> E[๐ Asia-Pacific]
end
subgraph "Content Delivery"
F[๐ค User Request] -->|"DNS Resolution"| G[๐ก Nearest Edge]
G -->|"Cache Hit"| H[โก Serve Cached]
G -->|"Cache Miss"| I[๐ Origin Fetch]
I --> J[๐พ GitHub Origin]
J --> G
G --> F
end
subgraph "Build Redundancy"
K[๐ Daily Build] -->|"Trigger"| L[โ๏ธ GitHub-Hosted<br>Runner]
L -->|"Success"| M[โ
Deploy]
L -->|"Failure"| N[๐ Manual Retry]
M --> O[๐ฆ Static Assets]
O --> J
end
style A fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style B fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style C,D,E fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
style F fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style G,H,I fill:#00E676,stroke:#00C853,stroke-width:2px,color:black,font-weight:bold
style J fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style K,L,N fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style M,O fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
classDef default font-weight:bold
Global Distribution:
Availability Features:
GitHub Pages SLA:
EU Parliament Monitor Targets:
Calculated Availability:
Content Delivery Network (CDN):
DNS Configuration:
euparliamentmonitor.hack23.com (GitHub Pages custom domain)hack23.github.ioEdge Caching:
Static Site Advantages:
Recovery Procedures:
1. GitHub Pages Outage:
2. Build Failure:
workflow_dispatch3. Repository Compromise:
4. European Parliament MCP Server Outage:
Build Resilience:
Content Resilience:
Infrastructure Resilience:
EU Parliament Monitor's resilience strategy leverages the inherent reliability of static site architecture combined with GitHub's infrastructure.
flowchart TD
subgraph "Resilience & Operational Readiness"
A[๐๏ธ Static Site<br>Architecture] --> B[๐ Resilience<br>Assessment]
B --> C[๐ Resilience<br>Characteristics]
C --> D[๐ Recovery Time<br>Objective: 24h]
C --> E[๐ Recovery Point<br>Objective: 1 day]
F[๐ Resilience<br>Validation] --> G[๐งช Build<br>Testing]
F --> H[๐ Deployment<br>Testing]
F --> I[๐จ Failover<br>Testing]
J[โก Operational<br>Readiness] --> K[๐ Runbooks]
J --> L[๐ฅ Response<br>Procedures]
J --> M[๐ Automated<br>Recovery]
N[๐ Business<br>Continuity] --> O[๐ CDN<br>Distribution]
N --> P[๐พ Git<br>Backup]
N --> Q[๐ Recovery<br>Plans]
end
style A fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style B,C fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style D,E fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style F,J,N fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style G,H,I,K,L,M,O,P,Q fill:#00E676,stroke:#00C853,stroke-width:2px,color:black,font-weight:bold
classDef default font-weight:bold
Inherent Resilience Advantages:
๐ฆ No Dynamic State:
๐ Reproducible Builds:
๐ Global Distribution:
๐พ Git-Backed Persistence:
Recovery Time Objective (RTO): 24 hours
| Scenario | Detection Time | Recovery Action | Total RTO | Impact |
|---|---|---|---|---|
| GitHub Pages Outage | <5 minutes | Wait for GitHub or deploy to alternative CDN | <1 hour | Low (GitHub SLA: 99.9%) |
| Build Failure | <5 minutes | Fix issue + re-run workflow | <1 hour | Low (daily updates acceptable) |
| Repository Compromise | <1 hour | Revert commits + rotate secrets | <4 hours | Medium (requires investigation) |
| MCP Server Outage | <5 minutes | Automatic fallback to cached data | 0 (automatic) | None (transparent failover) |
Recovery Point Objective (RPO): 1 day
| Data Type | Backup Frequency | Max Data Loss | Recovery Source |
|---|---|---|---|
| Source Code | Every commit | 0 (Git-backed) | GitHub repository, local clones |
| Generated Content | Daily build | 1 day | Regenerate from MCP data |
| Build Configuration | Every commit | 0 (Git-backed) | .github/workflows/ |
| Dependencies | Weekly scans | 0 (npm lockfile) | package-lock.json |
Build Failure Handling:
๐ Automatic Retry:
# Agentic workflows use gh-aw safe-outputs with single PR per run
# Retry is handled at the MCP client level via callToolWithRetry()
# and at the workflow level via manual re-dispatch
๐พ Dependency Caching:
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
๐ Manual Trigger:
workflow_dispatch event for manual executionโฐ Scheduled Execution:
Deployment Resilience:
deploy-s3.ymlRunbooks:
[RUNBOOK-001] Build Failure Response:
news-*.lock.yml workflownpm run generate-article -- --run <dir>workflow_dispatch[RUNBOOK-002] Deployment Failure Response:
[RUNBOOK-003] MCP Server Outage:
[RUNBOOK-004] Security Incident Response:
Response Teams:
Automated Recovery:
1. ๐ Multi-Region CDN Distribution:
2. ๐พ Git-Based Disaster Recovery:
3. ๐ Alternative Hosting Plans:
4. ๐ Build Reproducibility:
package-lock.json)Availability Metrics:
Build Metrics:
Recovery Capabilities:
EU Parliament Monitor implements automated security operations through GitHub's native security features and CI/CD automation.
flowchart TD
subgraph "Automated Security Maintenance"
A[โฑ๏ธ Weekly<br>Schedule] --> B[๐ Automated<br>Operations]
B --> C[๐ Dependency<br>Scanning]
B --> D[๐ ๏ธ Automated<br>Updates]
B --> E[๐ Code<br>Analysis]
B --> F[๐ Compliance<br>Checks]
C --> G[๐ Dependabot<br>Alerts]
D --> H[๐ Automated<br>PRs]
E --> I[๐ CodeQL<br>Results]
F --> J[โ
REUSE<br>Compliance]
G & H & I & J --> K[๐ฆ Security<br>Dashboard]
end
style A fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style B fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style C,D,E,F fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style G,H,I,J fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
style K fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
classDef default font-weight:bold
Configuration:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
day: 'monday'
time: '08:00'
timezone: 'Europe/Stockholm'
open-pull-requests-limit: 10
reviewers:
- 'pethers'
assignees:
- 'pethers'
commit-message:
prefix: 'chore(deps)'
include: 'scope'
Automated Actions:
Severity Handling:
| Severity | Response Time | Action | Auto-Merge |
|---|---|---|---|
| Critical | 24 hours | Immediate review + merge | โ No (breaking changes risk) |
| High | 7 days | Priority review + merge | โ No |
| Medium | 30 days | Standard review | โ ๏ธ If dev dependency |
| Low | 90 days | Batch with other updates | โ Yes (if dev dependency) |
Configuration:
# .github/workflows/codeql.yml
name: 'CodeQL Advanced'
on:
push:
branches: ['main']
pull_request:
branches: ['main']
schedule:
- cron: '0 8 * * 1' # Weekly Monday 08:00 UTC
jobs:
analyze:
name: Analyze (javascript-typescript)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
queries: security-extended
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: '/language:javascript-typescript'
Automated Scanning:
main, pull requests, weekly scheduledsecurity-extended (OWASP Top 10, CWE Top 25)Alert Management:
Build-Time Security Checks:
npm audit (every build):
- name: Run npm audit
run: npm audit --audit-level=moderate
HTML Validation (every build):
- name: Validate HTML
run: npm run validate:html
REUSE Compliance (every build):
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v4
Dependency Review (on PRs):
- name: Dependency Review
uses: actions/dependency-review-action@v4
Security Gates:
REUSE Compliance Automation:
# .github/workflows/reuse.yml
name: REUSE Compliance
on: [push, pull_request]
jobs:
reuse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v4
What It Checks:
LICENSES/ directory contains license textsBenefits:
GitHub Security Notifications:
| Event | Notification Channel | Response Time |
|---|---|---|
| Dependabot Alert | Email + GitHub UI | 24h (Critical), 7d (High) |
| CodeQL Finding | PR Comment + Email | Immediate (blocks merge) |
| Workflow Failure | <1 hour (during business hours) | |
| Secret Scanning | Email + Security Tab | Immediate |
Integration with External Tools:
Efficiency Gains:
Security Improvements:
EU Parliament Monitor implements comprehensive application-level security controls focused on input validation, output encoding, and content integrity for its static site generation pipeline.
| Layer | Control | Implementation |
|---|---|---|
| Schema Validation | JSON structure verification | MCP response schema validation before processing |
| Type Enforcement | TypeScript strict mode | Compile-time type safety with strict: true |
| Range Checking | Bounds validation | Date ranges, string lengths, numeric bounds |
| HTML Sanitization | XSS prevention | html-sanitize.ts strips dangerous HTML tags and attributes |
| Content Validation | Article quality scoring | article-quality-scorer.ts validates generated content |
article-html.ts uses safe template patterns with escapeHTML() for all dynamic contentvalidate-articles.ts checks all generated articles for structural integrityhtmlhint validates HTML5 standards compliancenews-metadata.ts ensures article metadata integrity across languagesISMS Alignment:
EU Parliament Monitor implements a defense-in-depth security strategy with multiple overlapping layers of protection, ensuring that a compromise of any single layer does not lead to complete security failure.
graph TB
subgraph "Defense-in-Depth Layers"
direction TB
A[๐ Edge/CDN Layer] --> B[๐ Network Layer]
B --> C[๐ก๏ธ Application Layer]
C --> D[๐ Data Layer]
D --> E[๐พ Storage Layer]
E --> F[๐๏ธ Infrastructure Layer]
F --> G[๐ Monitoring Layer]
A --> A1[GitHub Pages CDN<br>DDoS Protection<br>TLS 1.3]
B --> B1[HTTPS-Only<br>CSP Headers<br>Secure Headers]
C --> C1[Input Validation<br>XSS Prevention<br>Dependency Security]
D --> D1[No Persistent Data<br>Public Data Only<br>Sanitization]
E --> E1[Git-Backed Storage<br>Immutable History<br>Signed Commits]
F --> F1[GitHub Actions<br>Ephemeral Runners<br>Minimal Secrets]
G --> G1[CodeQL SAST<br>Dependabot<br>Audit Logs]
end
style A,B,C,D,E,F,G fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style A1,B1,C1,D1,E1,F1,G1 fill:#00E676,stroke:#00C853,stroke-width:2px,color:black,font-weight:bold
classDef default font-weight:bold
GitHub Pages CDN Protection:
Security Benefits:
HTTP Security Headers:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Note: HSTS and nosniff are provided by GitHub Pages. CSP is implemented via HTML meta tags in article pages. X-Frame-Options and Permissions-Policy are planned as future enhancements.
Network Controls:
Security Benefits:
Input Validation & Sanitization:
// src/utils/file-utils.ts
export function escapeHTML(str: string): string {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
export function isSafeURL(url: string): boolean {
try {
const parsed = new URL(url);
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
} catch {
return false;
}
}
Dependency Security:
package-lock.json ensures reproducible buildsCode Security:
Security Benefits:
Data Minimization:
Data Validation:
// src/clients/ep-mcp-client.ts - Build-time data validation
// MCP responses are validated and sanitized before HTML generation
const rawData = await mcpClient.callTool('get_meps', params);
const sanitizedName = escapeHTML(rawData.name);
const validUrl = isSafeURL(rawData.photoUrl) ? rawData.photoUrl : '';
Security Benefits:
Git-Backed Security:
Repository Security:
# Branch protection rules (main branch)
- Require pull request reviews: 1 reviewer
- Dismiss stale reviews: true
- Require status checks: [CodeQL, REUSE, npm audit]
- Require signed commits: false (future: true)
- Lock branch: false
Security Benefits:
GitHub Actions Security:
GITHUB_TOKEN (auto-generated)Build Environment:
permissions:
contents: read # Read repository
pages: write # Deploy to GitHub Pages
id-token: write # OIDC token for GitHub Pages
security-events: write # CodeQL results
Security Benefits:
Continuous Monitoring:
Audit Logging:
Security Benefits:
The defense-in-depth approach ensures:
Example Attack Scenario:
๐จ XSS Attack Attempt via European Parliament Data
โโ Layer 1 (CDN): โ
Passes (static content delivery)
โโ Layer 2 (Network): ๐ก๏ธ No JavaScript in output (architectural prevention)
โโ Layer 3 (Application): ๐งน escapeHTML() sanitizes malicious content
โโ Layer 4 (Data): โ
Schema validation rejects invalid input
โโ Layer 6 (Infrastructure): ๐ Build fails if XSS in templates
โโ Layer 7 (Monitoring): ๐ CodeQL detects XSS vulnerability in code
Result: Attack blocked by 4 independent layers
Note: This section provides a summary of the threat model. For comprehensive threat analysis including detailed STRIDE analysis, attack scenarios, and mitigation strategies, see THREAT_MODEL.md.
| Asset | Value | Confidentiality | Integrity | Availability |
|---|---|---|---|---|
| Generated News Articles | High | Public | High | Medium |
| European Parliament Data Accuracy | High | Public | High | Medium |
| Website Availability | Medium | N/A | N/A | Medium |
| Repository Code | Medium | Public | High | Medium |
| Git History | Medium | Public | High | Low |
Category: Injection (STRIDE: Tampering)
Scenario: Malicious actor injects JavaScript via European Parliament API responses, executed in user browsers.
Attack Vector:
<script> tags in session titles or descriptionsLikelihood: Low (EP API is authoritative source, HTTPS prevents MITM)
Impact: High (could compromise user trust, redirect to malicious sites)
Controls:
escapeHTML() encodes all dangerous characters<, >, &, ", ' to HTML entitiesisSafeURL() validates URL schemes (http/https only)Residual Risk: Low - Multiple defense layers make successful XSS extremely difficult
MITRE ATT&CK Mapping: T1189 (Drive-by Compromise)
Category: Elevation of Privilege (STRIDE: Elevation of Privilege)
Scenario: Malicious code injected into npm dependency, executed during news generation.
Attack Vector:
Likelihood: Low (minimal dependencies, Dependabot alerts, code review)
Impact: High (could compromise repository, inject malicious content)
Controls:
Residual Risk: Low - Multiple validation layers and minimal attack surface
MITRE ATT&CK Mapping: T1195.002 (Supply Chain Compromise: Compromise Software Supply Chain)
Category: Information Disclosure / Tampering (STRIDE: Tampering)
Scenario: Incorrect or misleading news articles generated due to API changes, bugs, or data corruption.
Attack Vector:
Likelihood: Medium (APIs evolve, schema drift possible)
Impact: High (misinformation damages credibility, public trust)
Controls:
Residual Risk: Medium - Schema validation reduces risk, but manual review not automated
MITRE ATT&CK Mapping: T1565.001 (Data Manipulation: Stored Data Manipulation)
Category: Denial of Service (STRIDE: Denial of Service)
Scenario: GitHub Actions unavailable, preventing news generation.
Attack Vector:
Likelihood: Low (GitHub has high availability SLA)
Impact: Medium (24-hour RTO acceptable per classification)
Controls:
Residual Risk: Low - GitHub's infrastructure is highly reliable, manual trigger available
MITRE ATT&CK Mapping: T1499 (Endpoint Denial of Service)
Category: Tampering / Elevation of Privilege (STRIDE: Tampering, Elevation of Privilege)
Scenario: Attacker gains unauthorized access to repository, injects malicious code.
Attack Vector:
Likelihood: Low (GitHub account security, branch protection, code review)
Impact: High (could compromise website integrity, user trust)
Controls:
Residual Risk: Low - Multiple security layers prevent and detect unauthorized changes
MITRE ATT&CK Mapping: T1078 (Valid Accounts), T1190 (Exploit Public-Facing Application)
Category: Spoofing / Tampering (STRIDE: Spoofing, Tampering)
Scenario: Malicious MCP server provides false data or attempts to compromise news generator.
Attack Vector:
Likelihood: Very Low (MCP server runs locally, no external MCP server connections)
Impact: High (could inject malicious content, compromise integrity)
Controls:
Residual Risk: Very Low - MCP server process isolation and input validation prevent compromise
MITRE ATT&CK Mapping: T1557 (Adversary-in-the-Middle)
| Threat | Category | Likelihood | Impact | Residual Risk | Priority |
|---|---|---|---|---|---|
| XSS via Parliamentary Data | Injection | Low | High | Low | P3 |
| Supply Chain Attack | Privilege Escalation | Low | High | Low | P2 |
| Data Integrity Issues | Tampering | Medium | High | Medium | P1 |
| GitHub Actions Downtime | Denial of Service | Low | Medium | Low | P4 |
| Repository Compromise | Tampering | Low | High | Low | P2 |
| MCP Server Compromise | Spoofing | Very Low | High | Very Low | P5 |
Priority Key:
Risk Treatment Plan:
EU Parliament Monitor aligns with multiple compliance frameworks to ensure security, privacy, and operational excellence.
graph TD
subgraph "Compliance Integration"
A[๐๏ธ Compliance<br>Framework] --> B[๐ NIST CSF 2.0]
A --> C[๐ ISO 27001:2022]
A --> D[๐ก๏ธ CIS Controls v8.1]
A --> E[๐ช๐บ GDPR]
A --> F[๐ช๐บ NIS2 Directive]
A --> G[๐ช๐บ EU CRA]
B --> H[๐ฏ Govern]
B --> I[๐๏ธ Identify]
B --> J[๐ก๏ธ Protect]
B --> K[๐ Detect]
B --> L[โก Respond]
B --> M[๐ Recover]
C --> N[๐ฅ A.9 Access<br>Control]
C --> O[๐ A.8 Asset<br>Management]
C --> P[โ๏ธ A.5 Policies]
C --> Q[๐ก A.8 Security<br>Operations]
D --> R[๐ง Control 1:<br>Inventory]
D --> S[๐ Control 4:<br>Secure Config]
D --> T[๐ก๏ธ Control 10:<br>Malware Defense]
end
style A fill:#673AB7,stroke:#311B92,stroke-width:2px,color:white,font-weight:bold
style B,C,D,E,F,G fill:#00C853,stroke:#007E33,stroke-width:2px,color:white,font-weight:bold
style H,I,J,K,L,M fill:#2979FF,stroke:#0D47A1,stroke-width:2px,color:white,font-weight:bold
style N,O,P,Q fill:#FFD600,stroke:#FF8F00,stroke-width:2px,color:black,font-weight:bold
style R,S,T fill:#FF3D00,stroke:#BF360C,stroke-width:2px,color:white,font-weight:bold
classDef default font-weight:bold
Govern (GV)
Identify (ID)
Protect (PR)
Detect (DE)
Respond (RS)
Recover (RC)
A.5 Organizational Controls
A.8 Technological Controls
| CIS Control | Safeguard | Description | Implementation | IG Level | Status |
|---|---|---|---|---|---|
| 1 | 1.1 | Establish and maintain detailed enterprise asset inventory | SBOM (sbom.json), package.json | IG1 | โ |
| 2 | 2.1 | Establish and maintain software inventory | npm dependency tree, TypeScript source | IG1 | โ |
| 2 | 2.2 | Ensure authorized software is supported | Dependabot updates, Node.js 26 LTS in production | IG1 | โ |
| 4 | 4.1 | Establish and maintain secure configuration process | ESLint, Prettier, htmlhint rules | IG1 | โ |
| 4 | 4.7 | Manage default accounts | No default accounts (static site) | IG1 | N/A |
| 5 | 5.1 | Establish and maintain inventory of accounts | GitHub organization accounts | IG1 | โ |
| 5 | 5.3 | Disable dormant accounts | GitHub access review process | IG1 | โ |
| 6 | 6.1 | Establish access control foundation | GitHub MFA, branch protection rules | IG1 | โ |
| 6 | 6.2 | Establish access grants for least privilege | contents:write only for GitHub Actions | IG1 | โ |
| 7 | 7.1 | Establish vulnerability management process | Dependabot automated PRs, npm audit | IG1 | โ |
| 7 | 7.4 | Perform automated vulnerability scanning | CodeQL SAST weekly scans | IG2 | โ |
| 7 | 7.5 | Perform automated patch management | Dependabot auto-updates | IG2 | โ |
| 8 | 8.2 | Collect audit logs | GitHub Actions logs 90-day retention | IG1 | โ |
| 8 | 8.5 | Collect detailed audit logs | Git commit history (immutable) | IG2 | โ |
| 9 | 9.1 | Ensure use of only fully supported browsers | Static HTML/CSS/JS, no custom browser code | IG1 | N/A |
| 11 | 11.2 | Perform automated backups | Git distributed backup (all clones) | IG1 | โ |
| 11 | 11.3 | Protect recovery data | GitHub repository integrity | IG1 | โ |
| 12 | 12.2 | Establish network infrastructure management | No server infrastructure (static site) | IG1 | N/A |
| 14 | 14.1 | Establish/maintain security awareness | CONTRIBUTING.md, SECURITY.md | IG1 | โ |
| 16 | 16.1 | Establish secure application development process | CodeQL, ESLint security, branch protection | IG1 | โ |
| 16 | 16.2 | Establish secure coding training | Secure coding guidelines documented | IG2 | โ |
| 16 | 16.6 | Remediate detected software vulnerabilities | 7-day SLA for high CVEs, Dependabot | IG2 | โ |
| 18 | 18.1 | Establish penetration testing program | Future DAST implementation (Q3 2026) | IG3 | ๐ฎ |
Data Protection Principles:
| Principle | Implementation | Article |
|---|---|---|
| Lawfulness, Fairness, Transparency | Public data, no user tracking | Art. 5(1)(a) |
| Purpose Limitation | Single purpose: EU Parliament news | Art. 5(1)(b) |
| Data Minimisation | No PII collected, public data only | Art. 5(1)(c) |
| Accuracy | European Parliament authoritative source | Art. 5(1)(d) |
| Storage Limitation | No persistent user data stored | Art. 5(1)(e) |
| Integrity & Confidentiality | HTTPS, TLS 1.3, CSP headers | Art. 5(1)(f) |
| Accountability | ISMS policies, audit trail | Art. 5(2) |
Data Subject Rights:
Risk Management Measures (Article 21):
Reporting Obligations (Article 23):
Essential Cybersecurity Requirements:
| Requirement | Implementation | Annex I Reference |
|---|---|---|
| Secure by Default | HTTPS-only, CSP, minimal attack surface | Part I, ยง1 |
| Vulnerability Handling | Coordinated disclosure, 90-day embargo | Part I, ยง2 |
| Security Updates | Dependabot automated PRs, weekly scans | Part I, ยง2 |
| Software Bill of Materials | npm list --json > sbom.json |
Part I, ยง2(3) |
| Secure Development | CodeQL SAST, secure coding guidelines | Part II, ยง1 |
| Incident Reporting | SECURITY.md, GitHub Security Advisories | Part II, ยง2 |
Conformity Assessment:
| Framework | Evidence Documents | Repository Locations |
|---|---|---|
| ISO 27001 | SECURITY_ARCHITECTURE.md, ISMS-PUBLIC | This document, ISMS-PUBLIC |
| NIST CSF | THREAT_MODEL.md, WORKFLOWS.md | THREAT_MODEL.md, WORKFLOWS.md |
| CIS Controls | Security controls documentation | This document (Security Controls section) |
| GDPR | Privacy policy (no data collection) | This document (Data Protection section) |
| NIS2 | Incident response plan | SECURITY.md |
| EU CRA | SBOM, vulnerability disclosure | sbom.json, SECURITY.md |
Theme 5 โ Organizational Controls (5.1โ5.37)
| Control | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| 5.1 | Information security policies | ISMS-PUBLIC policy reference | โ | This document, ISMS-PUBLIC repo |
| 5.2 | Information security roles and responsibilities | CEO as document owner | โ | Document header |
| 5.9 | Inventory of information and other assets | Asset inventory in threat model | โ | Threat Model section |
| 5.12 | Classification of information | Public data classification | โ | Executive Summary, Classification Framework |
| 5.14 | Information transfer | TLS 1.3 in transit | โ | Network Security section |
| 5.15 | Access control | Minimal GitHub Actions permissions | โ | Authentication & Authorization section |
| 5.16 | Identity management | GitHub account MFA | โ | GitHub organization settings |
| 5.17 | Authentication information | Code review requirements | โ | Branch protection rules |
| 5.24 | Information security incident management planning and preparation | GitHub Issues for incidents | โ | CONTRIBUTING.md |
| 5.29 | Information security during disruption | Manual trigger, cached content | โ | Infrastructure Security section |
| 5.36 | Compliance with policies, rules and standards | This document | โ | Compliance Matrix section |
| 5.37 | Documented operating procedures | CI/CD workflows documented | โ | .github/workflows/ |
Theme 6 โ People Controls (6.1โ6.8)
| Control | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| 6.3 | Information security awareness, education and training | CONTRIBUTING.md security guidance | โ | CONTRIBUTING.md |
Theme 7 โ Physical Controls (7.1โ7.14)
| Control | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| 7.10 | Storage media | Git-based version control | โ | GitHub repository |
Theme 8 โ Technological Controls (8.1โ8.34)
| Control | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| 8.3 | Information access restriction | GITHUB_TOKEN auto-expiry | โ | GitHub Actions configuration |
| 8.7 | Protection against malware | CodeQL, ESLint security | โ | Application Security section |
| 8.8 | Management of technical vulnerabilities | Dependabot, npm audit | โ | Dependency Security section |
| 8.13 | Information backup | Git version control | โ | GitHub repository |
| 8.15 | Logging | GitHub Actions logs | โ | GitHub Actions audit logs |
| 8.16 | Monitoring activities | Dependabot & CodeQL continuous scans | โ | Security Operations section |
| 8.20 | Networks security | HTTPS only, localhost MCP | โ | Network Security section |
| 8.24 | Use of cryptography | TLS 1.3, GitHub Pages HTTPS | โ | Network Security section |
| 8.25 | Secure development lifecycle | SAST, dependency scanning | โ | Application Security section |
| 8.27 | Secure system architecture and engineering principles | Code review, branch protection | โ | Security Operations section |
| 8.33 | Test information | No production data in tests | โ | test/fixtures/ uses mock data |
Overall ISO 27001:2022 Compliance: โ Compliant (25/25 applicable controls implemented)
| Subcategory | Description | Implementation | Status |
|---|---|---|---|
| GV.OC-01 | Organizational mission understood and informs cybersecurity risk management | Democratic transparency mandate | โ |
| GV.OC-05 | Outcomes, capabilities, and services that the organization depends on are understood and communicated to supply chain | Public ISMS documentation | โ |
| GV.RM-01 | Risk management objectives are established and agreed to by organizational stakeholders | ISMS risk framework | โ |
| GV.RM-02 | Risk appetite and risk tolerance statements are established, communicated, and maintained | Low risk tolerance (public platform) | โ |
| GV.PO-01 | Policy for managing cybersecurity risks is established based on organizational context | ISMS-PUBLIC policies | โ |
| GV.RR-01 | Organizational leadership is responsible and accountable for cybersecurity risk | CEO document ownership | โ |
| GV.SC-01 | A cybersecurity supply chain risk management program, strategy, objectives, policies, and processes are established | Dependabot, SHA-pinned actions | โ |
| GV.SC-06 | Planning and due diligence are performed to reduce risks before entering into formal supplier or other third-party relationships | Minimal dependencies, SCA scanning | โ |
| ID.AM-01 | Inventories of hardware managed by the organization are maintained | SBOM, package.json, GitHub repo | โ |
| ID.AM-02 | Inventories of software, services, and systems managed by the organization are maintained | npm dependency tree, Dependabot | โ |
| ID.AM-08 | Systems, hardware, software, services, and data are managed throughout their life cycles | ARCHITECTURE.md C4 diagrams | โ |
| ID.RA-01 | Vulnerabilities in assets are identified, validated, and recorded | CodeQL SAST, Dependabot SCA | โ |
| ID.RA-05 | Threats, vulnerabilities, likelihoods, and impacts are used to understand inherent risk and inform risk response prioritization | THREAT_MODEL.md STRIDE analysis | โ |
| ID.RA-06 | Risks are prioritized, responded to, and communicated to applicable stakeholders | Risk register, threat model | โ |
| ID.IM-01 | Improvements are identified from security assessments | Annual security review cycle | โ |
| PR.AA-01 | Identities and credentials for authorized users, services, and hardware are managed by the organization | GitHub MFA, auto-expiring GITHUB_TOKEN | โ |
| PR.AA-05 | Access permissions, entitlements, and authorizations are defined in a policy, managed, enforced, and reviewed | Branch protection, CODEOWNERS, least privilege | โ |
| PR.AT-01 | Personnel are provided with awareness and training so that they possess the knowledge and skills to perform general tasks with cybersecurity risks in mind | CONTRIBUTING.md, SECURITY.md | โ |
| PR.DS-01 | The confidentiality, integrity, and availability of data-at-rest are protected | Git repository integrity, immutable history | โ |
| PR.DS-02 | The confidentiality, integrity, and availability of data-in-transit are protected | TLS 1.3 HTTPS-only, GitHub Pages enforcement | โ |
| PR.DS-10 | The confidentiality, integrity, and availability of data-in-use are protected | No PII processing, public data only | โ |
| PR.IR-01 | Networks and environments are protected from unauthorized logical access and usage | No server network, localhost MCP only | โ |
| PR.IR-02 | The organization's technology assets are protected from environmental threats | No sensitive data collected | โ |
| PR.PS-01 | Configuration management practices are established and applied | ESLint config, branch protection rules | โ |
| PR.PS-02 | Software is maintained, replaced, and removed commensurate with risk | Dependabot, npm audit, Node.js LTS | โ |
| DE.AE-02 | Potentially adverse events are analyzed to better characterize them and detect cybersecurity incidents | GitHub Security Alerts, CodeQL findings | โ |
| DE.AE-06 | Information on adverse events is provided to authorized staff and tools | Public SECURITY.md, GitHub Security Advisories | โ |
| DE.CM-01 | Networks and network services are monitored to find potentially adverse events | Dependabot, CodeQL, npm audit continuous scanning | โ |
| DE.CM-09 | Computing hardware and software, runtime environments, and their data are monitored to find potentially adverse events | GitHub Actions logs, audit trail | โ |
| RS.MA-01 | The incident response plan is executed in coordination with relevant third parties once an incident is declared | SECURITY.md incident procedures | โ |
| RS.AN-03 | Analysis is performed to establish what has taken place during an incident and the root cause of the incident | Git history, Actions logs forensics | โ |
| RS.CO-02 | Internal and external stakeholders are notified of incidents in a timely manner | GitHub Security Advisories, SECURITY.md | โ |
| RS.MI-02 | Incidents are contained | Revert commits, disable workflows | โ |
| RC.RP-01 | The recovery portion of the incident response plan is executed once initiated from the incident response process | BCPPlan.md recovery procedures | โ |
| RC.CO-03 | Recovery activities and progress in restoring operational capabilities are communicated to designated internal and external stakeholders | GitHub Issues, SECURITY.md | โ |
| RC.IM-01 | Recovery plans incorporate lessons learned | Post-incident reviews documented | โ |
Overall NIST CSF 2.0 Compliance: โ Aligned (36/36 subcategories implemented across all 6 functions: GV, ID, PR, DE, RS, RC)
| Article | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| Art. 5 | Principles of Processing | No PII collected | โ | No tracking, no forms, static site |
| Art. 25 | Data Protection by Design | Security by design architecture | โ | Executive Summary, no PII by design |
| Art. 30 | Records of Processing | No processing of personal data | โ | Static site, no user data |
| Art. 32 | Security of Processing | Defense-in-depth controls | โ | Security Controls section |
| Art. 33 | Breach Notification | Incident response via GitHub Issues | โ | CONTRIBUTING.md |
| Art. 35 | DPIA | Not required (no PII) | โ | N/A - no high-risk processing |
GDPR Compliance: โ Compliant - No personal data processing, data protection by design
DPIA Required: โ No - Static website with no PII collection
| Article | Requirement | Implementation | Status | Evidence |
|---|---|---|---|---|
| Art. 20 | Cybersecurity Risk Management | Threat modeling, risk assessment | โ | Threat Model section |
| Art. 21 | Cybersecurity Measures | Defense-in-depth controls | โ | Security Controls section |
| Art. 21(2)(a) | Risk Analysis & Security Policies | ISMS-PUBLIC policy framework | โ | ISMS alignment throughout |
| Art. 21(2)(b) | Incident Handling | GitHub Issues, audit logs | โ | Security Operations section |
| Art. 21(2)(c) | Business Continuity | RTO/RPO defined, manual trigger | โ | Executive Summary |
| Art. 21(2)(d) | Supply Chain Security | Dependabot, SHA-pinned actions | โ | Dependency Security section |
| Art. 21(2)(e) | Effectiveness of Measures | Annual review, monitoring | โ | Document header (annual review) |
| Art. 23 | Incident Reporting | 24-hour reporting to CSIRT | โ ๏ธ | Future implementation |
NIS2 Compliance: โ Compliant - 7/8 requirements implemented Gap: Automated CSIRT reporting (future enhancement)
| Requirement | Implementation | Status | Evidence |
|---|---|---|---|
| SBOM | Generated for releases | โ | .github/workflows/release.yml |
| Vulnerability Disclosure | Public security advisories | โ | GitHub Security Advisories |
| Security Updates | Dependabot automated updates | โ | .github/dependabot.yml |
| Security by Design | Threat modeling, secure architecture | โ | This document |
| Conformity Assessment | Annual security review | โ | Document header |
CRA Alignment: โ Aligned - All applicable requirements implemented
Current Monitoring:
Future Monitoring (FUTURE_SECURITY_ARCHITECTURE.md):
Incident Classification:
Response Procedures:
Communication:
See dedicated ๐ Vulnerability Management section above for comprehensive scanning, SLA targets, and remediation processes.
| Metric | Target | Current | Status |
|---|---|---|---|
| Known Vulnerabilities | 0 | 0 | โ |
| Dependabot Alert Response Time | < 7 days | < 48 hours | โ |
| Code Coverage | > 80% | 82%+ | โ |
| CodeQL Findings | 0 critical/high | 0 | โ |
| Security Test Pass Rate | 100% | 100% | โ |
| Uptime SLA | > 99% | GitHub Pages SLA | โ |
Automated Testing:
Test Coverage:
EU Parliament Monitor demonstrates security excellence through public, verifiable evidence per Hack23 ISMS Open Source Policy:
| Badge | Status | Score/Level | Description |
|---|---|---|---|
| OpenSSF Scorecard | โ Implemented | Target โฅ7.0 | Supply chain security assessment |
| CII Best Practices | ๐ Registration Pending | Target: Passing | Open source development best practices |
| SLSA Provenance | โ Implemented | Level 3 | Build attestations and SBOM generation |
| SonarCloud | โ Implemented | Target: A | Code quality and security analysis |
| FOSSA | ๐ Setup Required | Target: Clean | License compliance scanning |
| REUSE | โ Implemented | Passing | FSFE license header compliance |
Badge Links:
The release workflow implements documentation-as-code principles, automatically generating comprehensive technical documentation with every release:
Documentation Pipeline:
graph LR
A[Release Trigger] --> B[Run Tests]
B --> C[Generate Coverage]
C --> D[Generate API Docs]
D --> E[Copy Reports]
E --> F[Create Index]
F --> G[Commit to Main]
G --> H[Deploy to GitHub Pages]
| Documentation Type | Generator | Security Controls |
|---|---|---|
| API Documentation | JSDoc | Input sanitization, no script injection |
| Test Coverage | Vitest HTML | Static HTML, no dynamic content |
| E2E Test Reports | Playwright | Screenshots sanitized, no PII |
| Documentation Index | Custom script | Static generation, XSS-safe |
Integrity:
Transparency:
Compliance:
| Control | Implementation | Purpose |
|---|---|---|
| Static Generation | No server-side execution | Eliminates injection attacks |
| Input Sanitization | JSDoc, HTML encoding | Prevents XSS in generated docs |
| Access Control | GitHub Pages authentication | Public read, write via workflow only |
| Audit Trail | Git commits for all changes | Complete history and accountability |
| Attestations | SLSA Level 3 provenance | Verifiable documentation integrity |
See FUTURE_WORKFLOWS.md for planned documentation improvements:
EU Parliament Monitor implements a security-by-design architecture with defense-in-depth controls appropriate for a public information platform. The static site architecture eliminates common attack vectors (SQL injection, session hijacking, server-side vulnerabilities) while maintaining transparency and accessibility.
Key Security Strengths:
Residual Risks:
Future Enhancements:
Document Approval:
| Role | Name | Date | Signature |
|---|---|---|---|
| CEO (Document Owner) | [Name] | 2026-05-03 | [Electronic] |
| CISO | [Name] | 2026-05-03 | [Electronic] |
Next Review Date: 2027-05-03
This document is maintained as part of Hack23 AB's Information Security Management System (ISMS)
ISMS Framework: Hack23/ISMS-PUBLIC