🔐 Security-by-Design for European Parliament Intelligence
🎯 Comprehensive Security Framework for Multi-Language News Platform
📋 Document Owner: CEO | 📄 Version: 2.1 | 📅 Last Updated:
2026-04-20 (UTC)
🔄 Review Cycle: Annual | ⏰ Next Review: 2027-04-20
🏷️ 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.40+ (post-2026-04-24 aggregator migration) publishes 1927 static HTML articles across 14 languages and 8 article types (breaking, week-ahead, week-in-review, month-ahead, month-in-review, committee-reports, motions, propositions), generated by 9 unified gh-aw agentic workflows (8 news-<type>.md article workflows + news-translate.md for 14-language flush translation). 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.
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:
- Breaking News: Rapid-response coverage of urgent parliamentary developments
- Week Ahead: Preview of upcoming parliamentary events
- Week In Review: Analysis of the previous week's activities
- Month Ahead: Preview of upcoming monthly parliamentary events
- Month In Review: Analysis of the previous month's activities
- Committee Reports: Analysis of committee activities
- Propositions: Legislative proposals analysis
- Motions: Parliamentary motions analysis
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
- ✅ Static Content: No server-side execution, no databases
- ✅ GitHub-Hosted: GitHub Pages infrastructure security
- ✅ Minimal Dependencies: 28 devDependencies, 1 production dependency (european-parliament-mcp-server), automated updates
- ✅ Automated Security: CodeQL, Dependabot, SonarCloud, npm audit
- ✅ Supply Chain Security: SHA-pinned GitHub Actions, SBOM generation, SLSA Level 3 provenance
- ✅ Workflow Hardening: StepSecurity harden-runner, OpenSSF Scorecard
- ✅ Ephemeral Execution: GitHub-hosted runners, no persistent infrastructure
| 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 |
The EU Parliament Monitor implements GitHub Agentic Workflows (gh-aw) with a comprehensive 5-layer defense-in-depth security model. This architecture ensures that AI-driven news generation operates within strict security boundaries while maintaining deterministic, auditable, and tamper-evident execution.
Purpose: Default-deny network access with allowlist-only egress control.
Implementation: Squid proxy enforces allowlist for all outbound network traffic from agentic workflow containers:
Allowed Endpoints:
- ✅ GitHub API:
api.github.com,github.com(workflow control, PR creation) - ✅ npm Registry:
registry.npmjs.org(dependency installation) - ✅ European Parliament MCP Gateway:
host.docker.internal:80/mcp/european-parliament(Docker bridge, local-only) - ✅ World Bank MCP: World Bank data integration
- ✅ IMF Data Services:
dataservices.imf.org/REST/SDMX_3.0/(economic context data) - ✅ LLM APIs: Copilot API, Claude API, Codex API (AI inference)
Default Behavior: All other outbound connections are blocked (default-deny).
Security Benefits:
- Prevents data exfiltration
- Blocks command-and-control channels
- Mitigates supply chain compromise (no arbitrary package downloads)
- Enforces principle of least privilege at network layer
Purpose: Restricted shell execution environment with pattern-based exploit prevention.
Security Controls:
-
Blocked Shell Patterns (prompt injection defense):
- ❌ Nested
$()inside$(( ))arithmetic expansion - ❌
${VAR:-$(cmd)}default-with-fallback command substitution - ❌ Complex variable indirection chains
- ❌ Nested
-
Schema-Enforced Tool Calls:
- Every bash tool invocation requires explicit
command+descriptionfields - Tool schema validation prevents obfuscated command injection
- TypeScript type safety enforced at compile time
- Every bash tool invocation requires explicit
-
Container Isolation:
- Read-only file system for system directories
- No privileged escalation (
--cap-drop=ALL) - Resource limits (CPU, memory) enforced by Docker
ISMS Alignment: Secure Development Policy § Shell Security
Purpose: Limit blast radius of AI-generated content changes through size and review controls.
Implementation:
-
create-pull-requestSafe-Output Limits:- Default max patch size: 1024 KB (enforced for most workflows)
- Extended limit for
news-translate.md: 10240 KB (14-language fan-out requires larger patches) - Single PR per workflow run (enforced by gh-aw framework)
-
Mandatory Review Workflow:
- All AI-generated PRs require human review before merge
- Branch protection rules enforce status checks + approvals
- No auto-merge allowed for content changes
Security Benefits:
- Prevents repository flooding attacks (size-bounded patches)
- Ensures human-in-the-loop oversight for AI-generated content
- Traceable approval chain for all changes
Purpose: Immutable forensic trail of all tool invocations for post-incident analysis.
Implementation:
- Log Format: JSON Lines (JSONL) — one tool call per line
- Log File:
agent-stdio.login workflow run artifacts - Retention: Retained as GitHub Actions workflow artifacts (90-day default retention)
Logged Data:
- Timestamp (ISO 8601)
- Tool name + parameters
- Input data (sanitized)
- Output/response (truncated if >10KB)
- Execution duration
- Exit code/status
Use Cases:
- Security incident investigation
- Compliance auditing (ISMS § Audit & Logging)
- Workflow debugging and optimization
- Anomaly detection (baseline deviation)
Purpose: Deterministic, tamper-evident workflow execution with version-pinned toolchain.
Implementation:
-
gh aw compile --validate(pinned to v0.69.0):- Enforced by
.github/workflows/compile-agentic-workflows.yml - Any version drift = CI failure
- Version mismatch blocks PR merge
- Enforced by
-
Workflow Source Control:
- Source:
.github/workflows/*.md(human-readable, version-controlled) - Artifact:
.github/workflows/*.lock.yml(deterministic, compiled) - Compilation is reproducible (same input = same output)
- Source:
-
Branch Protection:
- Direct edits to
.lock.ymlfiles blocked by CODEOWNERS - Changes to
.mdsources trigger recompilation via CI - Recompiled
.lock.ymlmust match expected SHA-256 hash
- Direct edits to
Security Benefits:
- Prevents workflow tampering (lock files are deterministic)
- Ensures toolchain integrity (pinned gh-aw version)
- Branch protection enforces review-before-merge
- Audit trail for all workflow changes (Git history)
ISMS Alignment: Secure Development Policy § Change Management
graph TB
subgraph "Layer 5: Lock-File Compilation"
MD[.md Workflow Source]
COMPILE[gh aw compile v0.69.0]
LOCK[.lock.yml Artifact]
MD --> COMPILE
COMPILE --> LOCK
end
subgraph "Layer 4: JSONL Audit Trail"
LOG[agent-stdio.log]
ARTIFACT[Workflow Artifacts<br/>90-day Retention]
LOG --> ARTIFACT
end
subgraph "Layer 3: Safe-Outputs"
PR[create-pull-request]
SIZE[max-patch-size: 1024 KB]
REVIEW[Mandatory Human Review]
PR --> SIZE
SIZE --> REVIEW
end
subgraph "Layer 2: Sandboxed Runner"
DOCKER[Docker Container]
SHELL[Restricted Shell]
PATTERN[Blocked Patterns]
DOCKER --> SHELL
SHELL --> PATTERN
end
subgraph "Layer 1: AWF Firewall"
SQUID[Squid Proxy]
ALLOWLIST[Endpoint Allowlist]
DENY[Default Deny]
SQUID --> ALLOWLIST
ALLOWLIST --> DENY
end
subgraph "Agentic Workflow Execution"
RUN[Workflow Run]
end
LOCK --> RUN
RUN --> LOG
RUN --> PR
RUN --> DOCKER
RUN --> SQUID
style LOCK fill:#e8f5e9
style LOG fill:#e1f5ff
style PR fill:#ffe1e1
style DOCKER fill:#fff4e1
style SQUID fill:#ffe1e1
style RUN fill:#f0f0f0
Defense-in-Depth Principle: Each layer provides independent security controls. Compromise of any single layer does not bypass the entire security model.
ISMS Compliance:
- ISO 27001 Annex A.8.31 (Separation of development, testing, and production environments)
- NIST CSF 2.0 PR.AC-4 (Access permissions managed, incorporating least privilege)
- CIS Controls v8.1 Control 4.1 (Establish and maintain a secure configuration process)
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:80/mcp/european-parliament
Communication Model:
- Protocol: Local stdio JSON-RPC over Docker bridge network
- Trust Boundary: Docker bridge itself provides isolation (container-to-container communication)
- Transport Security: No TLS required — traffic never leaves the Docker host
- Authentication: Tokens extracted via
scripts/mcp-setup.sh(nojqdependency) - Client Library:
src/mcp/ep-mcp-client.ts(compiled toscripts/mcp/ep-mcp-client.js)- Reads
EP_MCP_GATEWAY_URLand auth environment variables at runtime - Type-safe TypeScript interfaces for all MCP tool schemas
- Reads
Security Considerations:
- Docker Bridge Isolation: Traffic confined to Docker internal network (
host.docker.internal) - Ephemeral Credentials: Auth tokens are workflow-scoped, expire after job completion
- No External Exposure: MCP gateway never exposed to public internet
- Input Validation: All MCP responses validated against TypeScript schemas before use
Endpoint: https://dataservices.imf.org/REST/SDMX_3.0/
Communication Model:
- Protocol: HTTPS (native
fetchAPI) - Transport Security: TLS 1.2+ / 1.3 enforced (Node.js 25 default)
- Authentication: Public API, no credentials required
- Request Timeout: Per-request
AbortControllertimeout enforced viaIMF_API_TIMEOUT_MSenvironment variable (default 30 000 ms)
Security Controls:
- Certificate Validation: Node.js built-in TLS certificate chain validation
- HTTPS-Only: IMF requests target the fixed
https://dataservices.imf.org/REST/SDMX_3.0/base URL (configurable viaIMF_API_BASE_URL) - Failure Handling: Network failures, non-2xx responses, and timeouts return an empty fallback payload (not cached/sample data) so downstream content falls back to the OR-gate (when
WAVE3_IMF_STRICT=false) or fails Stage-C (when strict mode is on) - Verification: Integration tests in
test/integration/mcp/imf-mcp.test.jsexercise the client with an injectedfetchImplto cover success and failure paths
Endpoint: Configured via worldbank-mcp@1.0.1 npm package
Communication Model:
- Protocol: MCP stdio (same model as EP MCP)
- Transport Security: Local-only, no network transit
- Authentication: None required (public World Bank API)
- Client Library: World Bank MCP client integrated via
.github/copilot-mcp.json
Security Controls:
- Package Integrity: npm provenance verification (SLSA L3)
- Version Pinning: Exact version lock in
package-lock.json - Vulnerability Scanning: Dependabot monitors
worldbank-mcpfor CVEs - Input Validation: World Bank API responses validated before use
Purpose: Detect upstream MCP tool schema changes that could break workflows.
Implementation:
-
Canonical Tool Lists (exported from the MCP client modules):
IMF_MCP_TOOLSinsrc/mcp/imf-mcp-client.ts— expected IMF economic data toolsWORLD_BANK_MCP_TOOLSinsrc/mcp/worldbank-mcp-client.ts— expected World Bank data tools- (No canonical
EP_MCP_TOOLSexport exists yet insrc/mcp/ep-mcp-client.ts; see CRA-ASSESSMENT.md §5ᵇ gap table row 13.)
-
Integration Tests:
test/integration/mcp/imf-mcp.test.jsasserts the expected IMF tool list matchesIMF_MCP_TOOLStest/integration/mcp/worldbank-mcp.test.jsasserts the expected World Bank tool list matchesWORLD_BANK_MCP_TOOLS- Any upstream tool rename, addition, or removal for IMF/WB = test failure
- Blocks PR merge until drift is reviewed and the canonical lists are updated
- EP MCP coverage is provided by
test/integration/mcp-integration.test.js(contract suite), pending a dedicatedEP_MCP_TOOLSdrift guard
-
Semantic Versioning Enforcement:
- Breaking changes to MCP server require major version bump
- CI/CD fails if MCP server version doesn't match expected semver range
- Manual review required for major version upgrades
Drift Detection Benefits:
- Early Warning: Detect breaking changes before production deployment
- Change Approval: Enforce review for upstream schema changes
- Audit Trail: Git history tracks when and why tool lists changed
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):- IMF SDMX 3.0 evidence required for every economic claim
- Activated by
WAVE3_IMF_STRICT=trueenvironment variable (parsed byisWave3IMFStrictEnabled) - Will become the default in Wave-4
-
Wave-2 OR-gate (default) (
articlePolicyHasEconomicContext):- Accepts World Bank OR IMF evidence
- Pre-Wave-2 articles citing only World Bank remain green
- The default validator path until Wave-4 flips the strict gate on
-
Legacy soft-check (
articlePolicyHasWorldBank):- Retained as a non-breaking helper for diagnostic reporting and historical tests
- No longer the primary validator gate
Resilience Benefits:
- Editorial discipline: Wave-3 mandates IMF as the single authoritative economic source — eliminates ambiguity over which dataset takes precedence
- Graceful degradation: When
WAVE3_IMF_STRICTisfalse(default), workflows still succeed on WB-only evidence for back-compat - Diverse sources for non-economic context: WB retained for health, education, social, environment, demographics, defence, agriculture, innovation, governance — IMF does not cover these
Configuration File: .github/copilot-mcp.json
Purpose: Centralized registry of all MCP servers used by the project.
Change Management:
- Classification: Changes to
.github/copilot-mcp.jsonare Normal Changes under ISMS Change Management Policy - Review Required: All MCP server additions/removals require PR review
- Validation: CI tests verify MCP server availability after configuration changes
- Rollback: Git history allows instant rollback to previous working config
Example Configuration:
{
"mcpServers": {
"european-parliament": {
"command": "npx",
"args": ["-y", "european-parliament-mcp-server@1.2.15"],
"env": {
"EP_MCP_GATEWAY_URL": "http://host.docker.internal:80/mcp/european-parliament"
}
},
"worldbank": {
"command": "npx",
"args": ["-y", "worldbank-mcp@1.0.1"]
}
}
}ISMS Alignment:
- Change Management Policy — Normal Change classification
- Third Party Management — Vendor risk assessment
- Vulnerability Management — MCP dependency scanning
| 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 |
- 🔐 ISMS Policy Alignment
- 🏗️ System Context (C4 Level 1)
- 📦 Container Architecture (C4 Level 2)
- 🔧 Component Architecture (C4 Level 3)
- 🔒 Security Controls
- 📜 Data Integrity & Auditing
- 📊 Session & Action Tracking
- 🔍 Threat Detection & Security Event Monitoring
- 🔍 Vulnerability Management
- ⚙️ Configuration & Compliance Management
- 📈 Security Monitoring & Analytics
- 🏗️ High Availability & Resilience
- ⚡ Resilience & Operational Readiness
- 🤖 Automated Security Operations
- 🛡️ Application Security Controls
- 🏆 Defense-in-Depth Strategy
- 🎯 Threat Model
- 📋 Compliance Framework Mapping
- ✅ Compliance Matrix
- 🔍 Security Operations
- 📊 Security Metrics
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 | 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:
- Citizen/Reader ↔ CloudFront: HTTPS (TLS 1.2+/1.3)
- CloudFront ↔ S3 Origin: OAC (Origin Access Control), versioned bucket, private S3
- GH Actions Runner ↔ AWF Firewall ↔ Internet: Squid egress allowlist (Layer 1)
- gh-aw Container ↔ MCP Gateway: Docker bridge (local-only, no TLS required)
- gh-aw Container ↔ LLM API: HTTPS to Copilot/Claude/Codex APIs
- Maintainer ↔ GitHub Repo: 2FA, signed commits, required reviews, branch protection
- Release Pipeline ↔ npm Registry: OIDC provenance (SLSA L3)
- Release Pipeline ↔ AWS: OIDC federation (no long-lived keys)
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 "News Generation Container"
CLI[📝 generate-news-enhanced.ts<br/>TypeScript CLI Script]
TEMPLATE[🎨 article-template.ts<br/>HTML Generator]
CLIENT[🔌 ep-mcp-client.ts<br/>MCP Client Library]
end
subgraph "Index Generation Container"
IDX[📋 generate-news-indexes.ts<br/>Index Generator]
end
subgraph "Sitemap Generation Container"
SITE[🗺️ generate-sitemap.ts<br/>Sitemap 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 25 | Read/Write repo | Localhost only | None (ephemeral) |
| Index Generation | Node.js 25 | Read/Write repo | None | None (ephemeral) |
| Sitemap Generation | Node.js 25 | Read/Write repo | None | None (ephemeral) |
| MCP Server | Node.js 25 | Read-only | HTTPS to EP API | None (ephemeral) |
| Validation | Node.js 25 | 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:
- ✅ Minimal Permissions:
contents: writeonly, no admin/secrets access - ✅ Auto-expiring Tokens: GITHUB_TOKEN valid only for job duration
- ✅ SHA-pinned Actions: All actions pinned to commit SHA for supply chain security
- ✅ Branch Protection: Required reviews, status checks before merge
- ✅ No Persistent Credentials: Tokens destroyed after job completion
ISMS Alignment:
- Access Control Policy - Least privilege
- Secure Development Policy - CI/CD security
Control Implementation:
- ❌ No Authentication Required: Public content by design
- ✅ Read-Only Access: Users cannot modify content
- ✅ HTTPS Enforcement: GitHub Pages forces HTTPS
- ✅ No Server-Side Execution: No authentication bypass risks
Security Rationale:
- All content is public information from European Parliament
- No PII or sensitive data
- Read-only static files eliminate authentication attack surface
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:
- Schema Validation: MCP response structure validation
- Type Checking: Enforce expected data types (string, number, date)
- Range Checking: Validate date ranges, text lengths
- Encoding Enforcement: UTF-8 only, reject invalid encodings
Sanitization Controls:
- HTML Entity Encoding: Convert
<,>,&,",'to entities - Script Tag Removal: Strip all
<script>tags from input - Event Handler Removal: Remove
onclick,onerror, etc. - URL Validation: Validate and sanitize all href/src attributes
ISMS Alignment:
- Secure Development Policy - Input validation requirements
| 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:
- Classification Framework - Public data (Level 1)
- Cryptography Policy - TLS standards
Control Implementation:
- ✅ No User Tracking: No cookies, no analytics, no tracking scripts
- ✅ No Form Inputs: No data collection forms
- ✅ No User Accounts: No registration or login
- ✅ Static Content Only: No server-side processing of user data
- ✅ No JavaScript: No client-side scripts of any kind in generated pages
GDPR Compliance:
- Article 25 (Data Protection by Design): No PII by design
- Article 32 (Security of Processing): Public data only, no processing of personal data
- No Data Protection Impact Assessment (DPIA) required
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:
- ✅ No Hardcoded Secrets: All secrets stored in GitHub Secrets (encrypted at rest with libsodium sealed boxes)
- ✅ Ephemeral Tokens: GITHUB_TOKEN scoped to job duration and repository
- ✅ Least Privilege: Token permissions explicitly declared per workflow (
permissions:block) - ✅ Secret Scanning: GitHub secret scanning enabled to detect exposed credentials
- ✅ No Application-Managed Persistent Keys: Static site requires no application-managed long-lived cryptographic keys; all platform keys (TLS, GPG) are externally managed
- ✅ TLS 1.2+: All external connections use TLS 1.2 or higher; TLS 1.3 preferred where supported by peers (GitHub Pages, npm registry)
ISMS Alignment:
- Cryptography Policy — Key management, TLS standards, encryption requirements
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
- GitHub Pages enforces HTTPS for all connections
- TLS 1.3 with strong cipher suites
- Automatic HSTS header:
max-age=31536000
-
Localhost-Only MCP Communication
- MCP server binds to localhost only
- stdio/pipe communication (no network sockets)
- Process isolation within GitHub Actions runner
-
No Exposed Ports
- Static site: No server ports
- MCP server: Not exposed externally
- GitHub Actions: Ephemeral runners, no persistent infrastructure
-
Outbound Restrictions
- Only HTTPS to European Parliament API
- No other external connections
- DNS: GitHub-managed
ISMS Alignment:
- Network Security Policy - Network segmentation, TLS requirements
Current Security Headers (GitHub Pages Defaults):
GitHub Pages provides the following default security headers:
X-Content-Type-Options: nosniff- Prevent MIME sniffing
HTML 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 viasrc/templates/article-template.ts:377-399as 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 tojs/index-runtime.js(index pages) andjs/article-runtime.js(article pages). JSON-LD blocks usetype="application/ld+json"which is non-executable and exempt fromscript-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-originfetch/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 URL
CSP 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:
- Input Validation: Reject invalid data at API boundary
- HTML Sanitization: Remove dangerous tags (
<script>,<iframe>, etc.) - Entity Encoding: Convert special characters to HTML entities via
escapeHTML()insrc/utils/file-utils.ts - URL Validation:
isSafeURL()validates URL schemes (http/https only) - No JavaScript Execution: Generated articles contain zero JavaScript — XSS is architecturally impossible in the output
Testing:
- ESLint security plugin detects XSS patterns
- htmlhint validates HTML structure
- Unit tests validate sanitization functions
- Integration tests verify end-to-end XSS prevention
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:
- Minimal Dependencies: 28 devDependencies, 1 production dependency (european-parliament-mcp-server)
- npm provenance + SLSA Level 3: Release artifacts signed via OIDC publish (no long-lived npm token)
- AWS OIDC Federation:
.github/workflows/deploy-s3.ymluses OIDC (no long-lived AWS keys) - Dependabot: Weekly scans, auto-generate PRs for updates
- npm audit: CI validation, fail on moderate+ vulnerabilities
- gh-advisory-database: Gate on new dependencies before merge
- Version Locking: package-lock.json ensures reproducible builds
- SHA Pinning: GitHub Actions pinned to commit SHA
- Husky pre-commit: Local gate with lint-staged validation
- ESLint 10.2.1: sonarjs 4.0.3, security 4.0.0, jsdoc 62.9.0
- Vendored Libraries: Chart.js 4.5.1, D3 7.9.0 copied locally via
npm run copy-vendorwith SRI (no CDN risk) - CI/CD Gates:
codeql.yml,dependency-review.yml,scorecards.yml,reuse.yml(SPDX via REUSE.toml)
Current Dependencies:
- All devDependencies (28 packages) plus 1 production dependency (european-parliament-mcp-server)
- Latest versions with security patches
- No known vulnerabilities (npm audit clean)
ISMS Alignment:
- Vulnerability Management - Dependency scanning
- Secure Development Policy - SBOM requirements
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
- GitHub-hosted runners (Ubuntu latest)
- Destroyed after each job
- No persistent state or credentials
- Clean environment for each execution
-
Secrets Management
- GITHUB_TOKEN: Auto-generated, auto-expiring
- No custom secrets required for current operation
- Future: COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN for org access
-
Workflow Permissions
contents: write- Repository read/write only- No secrets, issues, or admin access
- Token scope limited to repository
-
Supply Chain Security
- All GitHub Actions SHA-pinned
- Dependabot monitors action updates
- SBOM generation for releases
-
Workflow Hardening (StepSecurity Harden Runner)
step-security/harden-runnerdeployed across all CI/CD workflows- Egress policy:
auditmode (monitors outbound network calls) - Egress policy:
blockmode on deployment workflows (only allowed endpoints) - Detects and reports anomalous network activity during builds
ISMS Alignment:
- Secure Development Policy - CI/CD security
- Access Control Policy - Least privilege
Hosting Security:
- ✅ HTTPS Enforcement: Automatic HTTPS redirect
- ✅ TLS 1.2+/1.3: Modern protocols enforced for all outbound HTTPS (Copilot API, Claude API, Codex API, IMF REST, WB MCP, GitHub API, npm registry, AWS)
- ✅ EP MCP: Local-only Docker bridge — no TLS required (trust boundary is Docker bridge itself)
- ✅ crypto.randomUUID() / crypto.randomBytes(): Secure RNG only;
Math.random()banned by ESLint - ✅ Deprecated Crypto Banned: MD5, SHA-1, DES, 3DES prohibited by ISMS policy
- ✅ DDoS Protection: GitHub's CDN infrastructure
- ✅ Automatic Patching: GitHub manages server updates
- ✅ No Server Configuration: Zero server attack surface
Static Site Security:
- ✅ No Databases: No SQL injection risk
- ✅ No Server-Side Code: No RCE vulnerabilities
- ✅ Read-Only Files: Users cannot modify content
- ✅ No User Input: No injection attack vectors
- ✅ No Sessions: No session hijacking risk
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_MARKERsentinels: Zero-tolerance for[AI_ANALYSIS_REQUIRED]markers
APIs:
scanHtmlForFallbackLeaks(htmlContent): Scan single HTML stringscanArticleHtmlFiles(directory): Scan all generated articles
Pre-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:
- CI fails on
[AI_ANALYSIS_REQUIRED]sentinel presence - PR merge blocked until all placeholder markers removed
- Human review required for all AI-generated content
Prompt Injection Defense:
- MCP data is stringly typed + sanitized via
src/utils/html-sanitize.ts - No untrusted input reaches shell (safe bash patterns enforced by Layer 2 sandboxing)
- Schema validation at API boundaries rejects malformed data
ISMS Alignment: AI Policy — AI content quality assurance
The 10 news generation workflows (breaking, week-ahead, week-in-review, month-ahead, month-in-review, committee-reports, motions, propositions, news-article-generator, news-translate) use the GitHub Agentic Workflows (gh-aw) framework with built-in security controls:
Workflow Hardening:
- ✅ Timeout Enforcement:
timeout-minutes: 45hard stop prevents runaway execution - ✅ Allowed Domains Whitelist: Network access restricted to
data.europarl.europa.eu,*.europa.eu,github.com, and required infrastructure endpoints viasafe-outputsconfiguration - ✅ Deterministic Branch Naming:
news/{type}-{date}pattern (e.g.,news/week-ahead-2026-02-23) prevents branch conflicts - ✅ PR Creation Limits: Maximum 1 pull request per workflow run enforced by gh-aw constraints
- ✅ Comment Limits: Maximum 1 comment per run, 65536 character limit, 10 mention limit
- ✅ Concurrency Control:
concurrency: gh-aw-${{ github.workflow }}prevents parallel execution of the same workflow - ✅ Read-Only Default Permissions:
permissions: {}at workflow level, elevated only where needed - ✅ SHA-Pinned Actions: All gh-aw actions pinned to specific commit SHA
MCP Data Resilience:
- 🔄 Fallback Data: Automatic fallback to cached/sample data if MCP server unavailable
- ⏰ Scheduled Retries: Multiple daily cron triggers ensure eventual success
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 |
- ✅ Git Audit Trail: Complete history of all content changes, author attribution, timestamps
- ✅ GitHub Actions Logs: Build execution logs retained for 90 days
- ✅ CodeQL SAST Reports: Security scan history with finding lifecycle
- ✅ Dependabot History: Dependency vulnerability alerts and resolution timeline
- ✅ PR Review Trail: Code review comments and approval history for all changes
- ✅ REUSE Compliance: License compliance audit trail via REUSE tool
ISMS Alignment:
- Information Security Policy — Audit logging and change tracking requirements
- Secure Development Policy — Data integrity evidence requirements
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:
- 🔑 Unique Run Identification: Each workflow run has a unique
GITHUB_RUN_ID - 👤 Trigger Attribution: Tracked via
GITHUB_ACTORandGITHUB_TRIGGERING_ACTOR - 🌿 Source Context: Branch (
GITHUB_REF), commit SHA (GITHUB_SHA) - ⏰ Temporal Tracking: Start time, end time, duration
- 🔄 Workflow Type: Scheduled (cron), manual (workflow_dispatch), push, pull_request
- 📊 Outcome: Success, failure, cancelled, skipped
Implementation:
# .github/workflows/generate-news.yml
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:
- 🔄 Operation Type: Checkout, setup, install, test, build, validate, deploy
- 📊 Step Context: Step name, job name, workflow name
- ✅ Success/Failure: Exit code, error messages
- ⏱️ Duration: Step execution time
- 📦 Artifacts: Generated files, logs, reports
Key Build Events Tracked:
- Node.js Setup: Version, cache hits
- Dependency Installation: npm install duration, vulnerability counts
- MCP Server Pre-installation: Success/failure, fallback triggers
- News Generation: Articles generated per language, processing time
- HTML Validation: W3C validation results, error counts
- Deployment: GitHub Pages deploy success, deployed URLs
Approach: No client-side tracking (no JavaScript analytics), privacy-first
Analytics Sources:
-
GitHub Pages CDN Logs (limited access):
- Aggregate page view counts
- Geographic distribution (country-level only)
- Referrer sources
- No individual visitor tracking
-
Repository Insights:
- Traffic views (14-day retention)
- Popular content
- Referrer analytics
- Clone/fork statistics
Privacy Protections:
- ❌ No cookies
- ❌ No fingerprinting
- ❌ No individual user tracking
- ❌ No third-party analytics (Google Analytics, etc.)
- ✅ Aggregate statistics only
- ✅ GDPR-compliant by design
GitHub Actions Logs:
- Retention: 90 days for public repositories
- Access: Repository maintainers only
- Contents: Full build logs, environment variables (secrets redacted)
- Export: Downloadable via GitHub CLI or API
Security Benefits:
- 🔍 Complete build reproducibility
- 🚨 Anomaly detection (unusual build patterns)
- 📊 Performance monitoring (build time trends)
- 🔒 Security event correlation (failed builds after dependency updates)
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:
- ✅ Successful builds (baseline for anomaly detection)
⚠️ Failed builds (potential security issues)- 🔄 Cancelled builds (manual intervention tracking)
- ⏱️ Timeout events (potential DoS indicators)
Authentication Events:
- 🔑 GitHub token usage (GITHUB_TOKEN)
- 🔐 Secret access patterns
- 👤 Actor changes (unexpected triggers)
Implementation:
# .github/workflows/generate-news.yml
- name: Monitor Build Security
if: failure()
run: |
echo "::warning::Build failed - security review required"
echo "Actor: ${{ github.actor }}"
echo "Commit: ${{ github.sha }}"Dependabot Alerts:
- 🔴 Critical vulnerabilities (CVSS ≥ 9.0)
- 🟠 High vulnerabilities (CVSS 7.0-8.9)
- 🟡 Medium vulnerabilities (CVSS 4.0-6.9)
- 🔵 Low vulnerabilities (CVSS < 4.0)
Automated Response:
- Weekly Dependabot scans
- Automated pull requests for patches
- Auto-merge for dev dependencies (low-risk)
- Manual review for breaking changes
Monitoring:
# npm audit in CI/CD pipeline
npm audit --audit-level=moderateCodeQL Analysis:
- Triggers: Every push to
main, every pull request - Languages: JavaScript/TypeScript (Node.js 25)
- Security queries: OWASP Top 10, CWE Top 25
- Findings: XSS, injection, path traversal, crypto issues
Alert Handling:
- 🚨 Critical: Block PR merge
⚠️ High: Require security review- 💡 Medium/Low: Create issue for remediation
Implementation:
# .github/workflows/codeql.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: '/language:javascript'Deployment Security:
- ✅ Successful deployments
⚠️ Failed deployments- 🔍 Asset integrity checks
- 📊 Deployment frequency anomalies
Health Checks:
- HTTPS certificate validation
- CSP header verification
- HTML validation results
- Link integrity checks
GitHub Security Dashboard:
- Location: Repository → Security tab
- Features:
- Dependabot alerts (real-time)
- Code scanning results (per commit)
- Secret scanning (not applicable for public repos)
- Security policies (SECURITY.md)
Notification Channels:
- Email: Security alerts to repository maintainers
- GitHub Notifications: In-app alerts
- Security Advisories: Public disclosure (90-day embargo)
Response SLAs:
- 🔴 Critical: 24 hours
- 🟠 High: 7 days
- 🟡 Medium: 30 days
- 🔵 Low: 90 days or next release
GitHub Actions Logs:
- Retention: 90 days
- Contents: Full workflow execution logs
- Access: Repository maintainers only
Security Alert History:
- Retention: Indefinite (until resolved)
- Status Tracking: Open, fixed, dismissed
- Audit Trail: All status changes logged
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 |
- ✅ Zero Known Vulnerabilities: npm audit clean, no open CodeQL alerts
- ✅ Dependabot PRs: Reviewed and merged within 48 hours
- ✅ CodeQL Findings: Triaged weekly, zero open critical/high findings
- ✅ Secret Scanning: No exposed credentials detected
- ✅ SBOM: Software Bill of Materials generated for supply chain transparency
| 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:
- Vulnerability Management — Scanning, assessment, and remediation processes
- Secure Development Policy — Security testing requirements
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-template.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 |
- ✅ Git Version Control: All configuration changes tracked with full audit history
- ✅ Required PR Reviews: No direct pushes to main branch
- ✅ CI/CD Validation: Every configuration change validated by automated pipeline
- ✅ Lock Files:
package-lock.jsonprevents dependency drift - ✅ SHA-Pinned Actions: GitHub Actions pinned to commit SHAs for reproducibility
- ✅ Strict TypeScript:
strict: truewith 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:
- Compliance Checklist — ISO 27001, NIST CSF, CIS Controls alignment
- Secure Development Policy — Configuration management requirements
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% |
- ✅ GitHub Advisory Database: Automatic CVE matching via Dependabot
- ✅ npm Security Advisories: Real-time vulnerability alerts for dependencies
- ✅ CodeQL Query Packs: Community-maintained security query updates
- ✅ ENISA Threat Landscape: Annual threat assessment reference (documented in THREAT_MODEL.md)
ISMS Alignment:
- Information Security Policy — Security monitoring requirements
- Vulnerability Management — Metrics and reporting standards
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:
- Edge Locations: 200+ worldwide via GitHub's CDN provider (Fastly)
- Geographic Coverage: All continents, optimized for EU access
- Latency: <50ms for 95% of European users
- Bandwidth: Unlimited for static content
Availability Features:
- ⚡ Automatic Failover: Multi-origin redundancy
- 🔄 Self-Healing: Failed edge nodes automatically replaced
- 📊 Load Balancing: Traffic distributed across edge locations
- 💾 Persistent Cache: Content cached at edge for fast delivery
GitHub Pages SLA:
- Uptime Target: 99.9% (GitHub's historical performance: >99.95%)
- Planned Downtime: None (rolling updates)
- Unplanned Downtime: <30 minutes/month average
EU Parliament Monitor Targets:
- Content Availability: 99.9% (inherits GitHub Pages SLA)
- Content Freshness: Daily updates (24-hour refresh cycle)
- Build Availability: 99.5% (GitHub Actions SLA)
Calculated Availability:
- Static Content: 99.9% (GitHub Pages)
- Build Process: 99.5% (GitHub Actions)
- Overall System: 99.4% (content always available, builds may fail)
Content Delivery Network (CDN):
- Primary: GitHub Pages CDN (Fastly)
- Regions: Global distribution with EU edge nodes
- Fallback: GitHub's origin servers
DNS Configuration:
- Primary:
euparliamentmonitor.hack23.com(GitHub Pages custom domain) - CNAME: Points to
hack23.github.io - CDN: Automatic edge routing via DNS
Edge Caching:
- Static Assets: 24-hour cache (HTML, CSS, images)
- Cache Invalidation: Automatic on new deployments
- Stale-While-Revalidate: Serve stale content during revalidation
Static Site Advantages:
- ✅ No Database: No data loss risk
- ✅ Git-Backed: Complete history in version control
- ✅ Reproducible: Rebuild from source at any time
- ✅ No State: Stateless architecture simplifies recovery
Recovery Procedures:
1. GitHub Pages Outage:
- Detection: Automated health checks, GitHub Status page
- Response: Wait for GitHub to resolve (typically <30 minutes)
- Mitigation: Deploy to alternative hosting (Netlify, Vercel) if extended
- Recovery Time: <1 hour (manual deployment to alternative CDN)
2. Build Failure:
- Detection: GitHub Actions workflow failure notification
- Response: Review logs, fix issues, re-run workflow
- Mitigation: Manual workflow trigger with
workflow_dispatch - Recovery Time: <1 hour (investigate + fix + rebuild)
3. Repository Compromise:
- Detection: Unauthorized commits, CodeQL alerts
- Response: Revert commits, rotate secrets, audit access
- Mitigation: Protected branches, required reviews, signed commits
- Recovery Time: <4 hours (investigation + remediation)
4. European Parliament MCP Server Outage:
- Detection: Build fails to fetch MCP data
- Response: Automatic fallback to cached data
- Mitigation: Pre-installed MCP server with sample data
- Recovery Time: 0 (automatic fallback)
Build Resilience:
- 🔄 Retry Logic: MCP client retries failed requests (3 attempts, exponential backoff)
- 💾 Data Caching: LRU cache prevents repeated API calls
- 🔄 Fallback Data: Sample MEP data if MCP unavailable
- ⏰ Scheduled Retries: Daily cron ensures eventual success
Content Resilience:
- 📦 Immutable Assets: Once deployed, content persists
- 🔄 Version Control: Full history in Git
- 📊 Atomic Deployments: All-or-nothing deployments
- 🔐 Branch Protection: Prevents accidental deletions
Infrastructure Resilience:
- ☁️ Ephemeral Runners: GitHub-hosted runners (no persistent state)
- 🌐 CDN Redundancy: Multiple edge nodes per region
- 🔒 Origin Redundancy: GitHub's distributed infrastructure
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:
- No session data to lose
- No database to corrupt
- No cache coherency issues
- Complete recovery from Git
-
🔄 Reproducible Builds:
- Deterministic build process
- Same input → same output
- Version-pinned dependencies
- Reproducible at any time
-
🌐 Global Distribution:
- GitHub Pages CDN (200+ edge locations)
- No single point of failure
- Automatic edge failover
- Multi-region redundancy
-
💾 Git-Backed Persistence:
- Complete history in version control
- Multiple repository copies (GitHub, local clones)
- Instant rollback capability
- Immutable commit history
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:
# .github/workflows/generate-news.yml - name: Generate News with Retry uses: nick-fields/retry@v2 with: timeout_minutes: 10 max_attempts: 3 command: npm run generate-news
-
💾 Dependency Caching:
- name: Cache npm dependencies uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
-
🔄 Manual Trigger:
workflow_dispatchevent for manual execution- Allows re-running failed builds immediately
- No waiting for next scheduled run
-
⏰ Scheduled Execution:
- Weekday crons: Committee (04:00), Propositions (05:00), Motions (06:00), Week Ahead (Fridays 07:00 UTC)
- Ensures fresh content even after failures
- Multiple retry opportunities per week
Deployment Resilience:
- Atomic Deployments: GitHub Pages deploys all files or none
- Rollback Capability: Revert commit + re-deploy previous version
- Zero-Downtime: Old content served until new deployment completes
- Immutable URLs: Assets never change once deployed
Runbooks:
-
[RUNBOOK-001] Build Failure Response:
- Check GitHub Actions logs
- Review error messages
- Test locally:
npm run generate-news - Fix issue → commit → push
- Or: manual trigger via
workflow_dispatch
-
[RUNBOOK-002] Deployment Failure Response:
- Verify GitHub Pages settings
- Check branch protection rules
- Review CNAME configuration
- Re-run deployment workflow
-
[RUNBOOK-003] MCP Server Outage:
- Verify MCP server status
- Check fallback data activation
- Monitor automated retries
- Escalate if outage >24 hours
-
[RUNBOOK-004] Security Incident Response:
- Follow SECURITY.md procedures
- Review GitHub Security Advisories
- Assess impact → contain → remediate → recover
- Document lessons learned
Response Teams:
- Primary: Repository maintainers (GitHub notifications)
- Escalation: Hack23 security team (security@hack23.com)
- External: European Parliament MCP team (for MCP issues)
Automated Recovery:
- ✅ Dependabot: Automatic PRs for dependency updates
- ✅ Branch Protection: Prevents accidental deletions
- ✅ Status Checks: Block merges that fail tests
- ✅ MCP Fallback: Automatic data fallback on failures
1. 🌐 Multi-Region CDN Distribution:
- GitHub Pages serves from 200+ edge locations
- EU users served from European edge nodes
- Automatic failover between edge nodes
- <50ms latency for 95% of EU users
2. 💾 Git-Based Disaster Recovery:
- Repository Copies: GitHub + local clones + forks
- Backup Strategy: Git inherently creates distributed backups
- Recovery: Clone from any copy + re-deploy
- Time to Recover: <1 hour
3. 📋 Alternative Hosting Plans:
- Primary: GitHub Pages
- Alternative 1: Netlify (similar static hosting)
- Alternative 2: Vercel (Edge Functions for future enhancements)
- Alternative 3: AWS S3 + CloudFront (if GitHub entirely unavailable)
4. 🔄 Build Reproducibility:
- Node.js version pinned (25.x, upgrading to 26.x LTS ~Apr 2026)
- Dependencies locked (
package-lock.json) - Environment variables documented
- Can rebuild on any system with Node.js
Availability Metrics:
- Current Uptime: 99.95% (last 12 months, per GitHub Pages)
- Mean Time to Recovery (MTTR): <1 hour
- Mean Time Between Failures (MTBF): 2,190 hours (91 days)
Build Metrics:
- Build Success Rate: 98.5% (last 90 days)
- Average Build Duration: 3m 45s
- Deployment Success Rate: 99.8%
Recovery Capabilities:
- Automated Recovery: 80% of failures (MCP fallback, retry logic)
- Manual Recovery Time: <1 hour (simple issues)
- Disaster Recovery Time: <4 hours (complex issues)
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:
- 🔍 Weekly Scans: Every Monday 08:00 Europe/Stockholm
- 🔄 Automated PRs: Up to 10 concurrent pull requests
- 🎯 Severity-Based: Critical/High prioritized first
- 👤 Auto-Assign: PRs assigned to maintainers
- ✅ Auto-Merge: Dev dependencies (low risk) auto-merged if tests pass
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 | |
| 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:
- ⚡ Trigger Events: Push to
main, pull requests, weekly scheduled - 🔍 Query Suite:
security-extended(OWASP Top 10, CWE Top 25) - 📊 Language: JavaScript/TypeScript
- 🚨 Blocking: High/Critical findings block PR merge
Alert Management:
- Auto-Dismiss: False positives marked by maintainers
- Auto-Close: Fixed issues automatically closed when remediated
- Auto-Comment: CodeQL comments on PRs with findings
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:
- ✅ All checks must pass before merge
- 🚫 Blocking: npm audit failures (moderate+)
⚠️ Warning: HTML validation errors (non-blocking)- ✅ Required: REUSE compliance
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@v4What It Checks:
- ✅ License Headers: All source files have SPDX identifiers
- ✅ License Files:
LICENSES/directory contains license texts - ✅ Copyright Statements: Copyright information present
- ✅ REUSE.toml: Configuration file valid
Benefits:
- 🔐 License Compliance: Automated license header verification
- 📋 Audit Trail: Every file's licensing clearly documented
- ⚡ Fast Feedback: <1 minute check on every push
- 🚫 Enforcement: Blocks PRs without proper licensing
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:
- 🔔 Slack/Discord: (Future) Webhook notifications
- 📧 Email: Built-in GitHub notifications
- 📱 Mobile: GitHub mobile app push notifications
Efficiency Gains:
- ⚡ Time Savings: ~8 hours/week (manual security checks eliminated)
- 🔄 Consistency: 100% of commits scanned (no human error)
- 🚀 Speed: Dependabot PRs created within 1 hour of vulnerability disclosure
- 📊 Coverage: 29/29 dependencies monitored (100%)
Security Improvements:
- 🔍 Early Detection: Vulnerabilities found before production
- 🛡️ Defense-in-Depth: Multiple automated security layers
- 📈 Continuous Improvement: Weekly scans catch new vulnerabilities
- 🔐 Supply Chain Security: Automated dependency review
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 |
- ✅ HTML Entity Encoding: All European Parliament data HTML-encoded before insertion
- ✅ CSP Hash-Based Script Allowlisting: Inline scripts allowed only via SHA-256 hash
- ✅ No Dynamic Script Generation: All content is static HTML, no runtime script evaluation
- ✅ Template Escaping:
article-template.tsuses safe template patterns - ✅ Multi-Language Safety: Content validators check all 14 language variants for XSS vectors
- ✅ Article Validation:
validate-articles.tschecks all generated articles for structural integrity - ✅ HTML Standards Compliance:
htmlhintvalidates HTML5 standards compliance - ✅ Accessibility Testing: WCAG 2.1 AA compliance via axe-core in E2E tests
- ✅ Link Integrity: Internal links validated during build process
- ✅ Metadata Consistency:
news-metadata.tsensures article metadata integrity across languages
ISMS Alignment:
- Secure Development Policy — Application security requirements, input validation standards
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:
- 🌐 Global Distribution: 200+ edge locations (Fastly-powered)
- 🛡️ DDoS Mitigation: Automatic traffic scrubbing at edge
- 🔒 TLS 1.3: Modern encryption for all traffic
- ⚡ Rate Limiting: Edge-level request throttling
- 🔐 Certificate Management: Automatic Let's Encrypt renewal
Security Benefits:
- Absorbs DDoS attacks before reaching origin
- Reduces attack surface (no exposed servers)
- Prevents protocol downgrade attacks
- Ensures always-on HTTPS
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:
- ✅ HTTPS-Only: No HTTP traffic (301 redirects)
- ✅ HSTS Preloading: Browser-enforced HTTPS
- ✅ No JavaScript: Architectural XSS prevention (no scripts to execute)
- ✅ No Inline Scripts: HTML output contains zero JavaScript
Security Benefits:
- Prevents man-in-the-middle attacks via HTTPS/HSTS
- XSS is architecturally prevented (no JavaScript in output)
- Prevents MIME-type confusion attacks
- Enforces secure communication
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:
- 📦 Minimal Dependencies: 28 devDependencies, 1 production dependency
- 🔒 Lock Files:
package-lock.jsonensures reproducible builds - 🔍 Weekly Scans: Dependabot monitors for vulnerabilities
- ✅ Automated Updates: Auto-merge dev dependency patches
Code Security:
- 🔍 CodeQL SAST: Scans for OWASP Top 10, CWE Top 25
- 📝 ESLint: Enforces secure coding patterns
- ⚡ Type Safety: TypeScript type system with strict checks
- 🔒 No eval(): No dynamic code execution
Security Benefits:
- Prevents XSS attacks via sanitization
- Detects vulnerabilities before production
- Minimizes supply chain attack surface
- Enforces secure coding standards
Data Minimization:
- No User Data: No authentication, no user accounts
- Public Data Only: European Parliament open data sources
- No Cookies: No tracking, no session data
- No Analytics: No third-party tracking (privacy by design)
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:
- GDPR compliance by design (no PII)
- No data breach risk (no sensitive data)
- Privacy-preserving (no tracking)
- Integrity protection (schema validation)
Git-Backed Security:
- 💾 Immutable History: All changes tracked in Git
- ✍️ Signed Commits: (Future) GPG-signed commits for authenticity
- 🔒 Branch Protection: Main branch requires reviews
- 🔐 Required Checks: Tests + CodeQL + REUSE must pass
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: falseSecurity Benefits:
- Complete audit trail of all changes
- Prevents unauthorized modifications
- Enables instant rollback
- Detects unauthorized access
GitHub Actions Security:
- ☁️ Ephemeral Runners: Fresh VM for each build
- 🔒 Minimal Secrets: Only
GITHUB_TOKEN(auto-generated) - 📌 SHA Pinning: Actions pinned to specific commits
- 🔐 Read-Only Tokens: Restricted permissions
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 resultsSecurity Benefits:
- No persistent infrastructure to compromise
- Secrets automatically rotated
- Supply chain attack prevention (pinned actions)
- Least privilege access (scoped tokens)
Continuous Monitoring:
- 🔍 CodeQL: Every push, every PR
- 📦 Dependabot: Weekly dependency scans
- 🔒 Secret Scanning: (GitHub built-in, not applicable for public repo)
- 📊 Workflow Monitoring: Build success/failure tracking
Audit Logging:
- Git History: All code changes logged
- GitHub Actions Logs: 90-day retention
- Security Events: Dependabot/CodeQL alerts logged
- Deployment History: GitHub Pages deployment log
Security Benefits:
- Early vulnerability detection
- Real-time security monitoring
- Complete audit trail
- Incident response capabilities
The defense-in-depth approach ensures:
- No Single Point of Failure: Compromise of one layer doesn't break entire security
- Overlapping Controls: Multiple layers protect same assets (e.g., XSS prevented by CSP + sanitization + CodeQL)
- Detection at Multiple Levels: Security events detected at application layer, infrastructure layer, and monitoring layer
- Graceful Degradation: If one control fails, others still provide protection
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:
- Attacker compromises EP API or performs MITM
- Injects malicious
<script>tags in session titles or descriptions - News generator includes malicious script in HTML
- User browsers execute script, potentially redirecting users to malicious sites
Likelihood: Low (EP API is authoritative source, HTTPS prevents MITM)
Impact: High (could compromise user trust, redirect to malicious sites)
Controls:
- ✅ Input Validation: Schema validation on MCP responses
- ✅ HTML Sanitization:
escapeHTML()encodes all dangerous characters - ✅ Entity Encoding: Convert
<,>,&,",'to HTML entities - ✅ URL Validation:
isSafeURL()validates URL schemes (http/https only) - ✅ No JavaScript: Generated articles contain zero JavaScript — XSS cannot execute in the output
- ✅ Testing: ESLint security plugin, XSS test cases
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:
- Attacker compromises npm package used by project
- Malicious code injected into package update
- Dependabot creates PR with compromised package
- PR merged without detecting malicious code
- GitHub Actions executes malicious code with write access to repository
Likelihood: Low (minimal dependencies, Dependabot alerts, code review)
Impact: High (could compromise repository, inject malicious content)
Controls:
- ✅ Minimal Dependencies: 28 devDependencies, 1 production dependency
- ✅ Dependabot: Automated vulnerability scanning, weekly updates
- ✅ npm audit: CI validation fails on moderate+ vulnerabilities
- ✅ Code Review: All PRs require review before merge
- ✅ Version Locking: package-lock.json prevents unexpected updates
- ✅ SBOM: Software Bill of Materials for releases
- ✅ SHA Pinning: GitHub Actions pinned to commit SHA
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:
- European Parliament API changes data format
- MCP client fails to validate new format
- News generator produces incorrect articles
- Public consumes misleading information about parliamentary activities
Likelihood: Medium (APIs evolve, schema drift possible)
Impact: High (misinformation damages credibility, public trust)
Controls:
- ✅ Schema Validation: Strict JSON schema validation on MCP responses
- ✅ Type Checking: Enforce expected data types
- ✅ Fallback Content: Graceful degradation to placeholder content
- ✅ Error Logging: All validation failures logged for investigation
- ✅ Manual Review: Generated content should be spot-checked (future)
⚠️ Automated Testing: Integration tests validate MCP client (current)- 🔮 Digital Signatures: Future enhancement for content verification
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:
- GitHub Actions experiences downtime (service interruption)
- Scheduled workflow fails to execute
- News articles not generated for extended period
- Website becomes stale, missing recent parliamentary activities
Likelihood: Low (GitHub has high availability SLA)
Impact: Medium (24-hour RTO acceptable per classification)
Controls:
- ✅ Manual Trigger: workflow_dispatch allows manual execution
- ✅ Cached Content: Previous articles remain available
- ✅ Monitoring: GitHub Actions status visible
- ✅ RTO/RPO Alignment: 24-hour RTO, 1-day RPO acceptable
- 🔮 Alternative Hosting: Future multi-region deployment
- 🔮 Uptime Monitoring: Future Pingdom/StatusCake integration
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:
- Attacker compromises developer account (phishing, credential theft)
- Pushes malicious code to repository
- Malicious code bypasses code review (social engineering)
- GitHub Actions executes malicious code with repository write access
- Malicious content injected into generated articles
Likelihood: Low (GitHub account security, branch protection, code review)
Impact: High (could compromise website integrity, user trust)
Controls:
- ✅ Branch Protection: Required reviews, status checks before merge
- ✅ Code Review: All changes reviewed by maintainers
- ✅ CodeQL: Automated SAST scanning detects common vulnerabilities
- ✅ ESLint Security: Static analysis for security issues
- ✅ MFA Required: GitHub organization requires MFA for all members
- ✅ Audit Logs: Git history provides immutable audit trail
- ✅ Revert Capability: Easy rollback via git revert
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:
- Attacker replaces legitimate MCP server with malicious version
- Malicious server returns crafted responses
- News generator processes malicious data
- Articles contain injected content or malicious links
Likelihood: Very Low (MCP server runs locally, no external MCP server connections)
Impact: High (could inject malicious content, compromise integrity)
Controls:
- ✅ Localhost Only: MCP server runs on localhost, not exposed externally
- ✅ Process Isolation: MCP server spawned by news generator, not pre-existing process
- ✅ Input Validation: All MCP responses validated against schema
- ✅ Ephemeral Execution: MCP server destroyed after news generation
- ✅ No Persistent State: MCP server has no persistence between runs
- 🔮 Mutual TLS: Future enhancement for authenticated MCP communication
- 🔮 Response Signatures: Future cryptographic verification of MCP responses
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:
- P1: High priority - requires additional controls
- P2: Medium priority - monitor and review
- P3: Low priority - current controls sufficient
- P4-P5: Very low priority - accept risk
Risk Treatment Plan:
- P1 (Data Integrity): Implement automated content verification (Q3 2026)
- P2 (Supply Chain, Repository): Continue current controls, annual review
- P3-P5: Accept residual risk, monitor for changes
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)
- GV.PO-01: Security policies aligned with ISMS-PUBLIC
- GV.RM-01: Risk management via threat model
- GV.SC-01: Supply chain security (Dependabot, SBOM)
Identify (ID)
- ID.AM-01: Asset inventory (threat model assets)
- ID.RA-01: Vulnerability scanning (Dependabot, CodeQL)
- ID.RA-02: Threat intelligence (GitHub Security Advisories)
Protect (PR)
- PR.AA-01: Authentication (GitHub CODEOWNERS, MFA)
- PR.DS-01: Data protection (HTTPS-only, CSP)
- PR.IP-01: Baseline configurations (ESLint, branch protection)
Detect (DE)
- DE.AE-02: Security event analysis (GitHub Actions logs)
- DE.CM-01: Network monitoring (CDN logs)
- DE.CM-08: Vulnerability scans (weekly Dependabot)
Respond (RS)
- RS.MA-01: Incident response plan (SECURITY.md)
- RS.CO-02: Coordinated disclosure (90-day embargo)
- RS.AN-03: Forensics (Git history, Actions logs)
Recover (RC)
- RC.RP-01: Recovery plan (runbooks)
- RC.CO-01: Communication plan (SECURITY.md)
- RC.IM-01: Recovery improvements (lessons learned)
A.5 Organizational Controls
- A.5.1: Information security policies ✅
- A.5.10: Acceptable use of information ✅
- A.5.23: Information security for cloud services ✅
A.8 Technological Controls
- A.8.3: Information backup ✅ (Git)
- A.8.9: Configuration management ✅ (Infrastructure as Code)
- A.8.23: Web filtering ✅ (CSP)
- A.8.24: Use of cryptography ✅ (TLS 1.3, HTTPS)
- A.8.28: Secure coding ✅ (CodeQL, ESLint)
| 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 25 Current (upgrading to Node.js 26 LTS ~Apr 2026) | 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:
- Not applicable (no personal data collected)
- No data processing activities requiring GDPR compliance
Risk Management Measures (Article 21):
- ✅ Risk analysis (threat model)
- ✅ Incident handling (SECURITY.md)
- ✅ Business continuity (resilience section)
- ✅ Supply chain security (Dependabot, SBOM)
- ✅ Secure development (CodeQL, ESLint)
- ✅ Vulnerability management (weekly scans)
Reporting Obligations (Article 23):
- 24-hour initial notification
- Incident details via security@hack23.com
- Follow-up reports as needed
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:
- Category: Non-critical product (static website generator)
- No CE marking required
- Self-assessment sufficient
- Documentation publicly available (this document)
| 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:
- ✅ GitHub Actions Logs: Job execution logs retained for 90 days
- ✅ CodeQL Alerts: Automated SAST findings triaged weekly
- ✅ Dependabot Alerts: Dependency vulnerabilities addressed within 7 days
- ✅ npm audit: Pre-commit and CI validation
- ✅ Git Audit Trail: Immutable commit history
Future Monitoring (FUTURE_SECURITY_ARCHITECTURE.md):
- 🔮 Uptime Monitoring: Pingdom/StatusCake (Q2 2026)
- 🔮 Error Tracking: Sentry integration (Q2 2026)
- 🔮 Security Metrics Dashboard: ISMS compliance scores (Q3 2026)
Incident Classification:
- P0 (Critical): Repository compromise, malicious content injection
- P1 (High): XSS vulnerability, dependency compromise
- P2 (Medium): Data integrity issues, workflow failures
- P3 (Low): Documentation errors, non-critical bugs
Response Procedures:
- Detection: GitHub Security Advisories, Dependabot alerts, manual reports
- Containment: Revert commits, disable workflows, remove compromised content
- Investigation: Review git logs, GitHub Actions logs, CodeQL findings
- Remediation: Apply patches, update dependencies, fix vulnerabilities
- Recovery: Deploy fixes, verify integrity, resume operations
- Post-Incident Review: Document lessons learned, update threat model
Communication:
- GitHub Issues for tracking
- Security Advisories for public disclosure
- CHANGELOG.md for user notification
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:
- ✅ Unit Tests: 87 tests covering core functionality
- ✅ Integration Tests: 82 tests for MCP client, workflows
- ✅ E2E Tests: 60+ Playwright tests (accessibility, responsive, multi-language)
- ✅ SAST: CodeQL, ESLint security plugin
- ✅ SCA: Dependabot, npm audit
- ✅ HTML Validation: htmlhint in CI
⚠️ DAST: Future implementation (Q3 2026)
Test Coverage:
- Lines: 82%+
- Branches: 83%+
- Functions: 89%+
- Statements: 82%+
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:
- View badges in README.md
- Maintenance procedures in README.md - Badge Maintenance
- OpenSSF Scorecard: https://scorecard.dev/viewer/?uri=github.com/Hack23/euparliamentmonitor
- REUSE Compliance: https://api.reuse.software/info/github.com/Hack23/euparliamentmonitor
- Build Attestations: https://github.com/Hack23/euparliamentmonitor/attestations/
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:
- ✅ Version Controlled: All documentation committed to git
- ✅ Immutable History: Complete audit trail of changes
- ✅ Reproducible: Regenerate docs from any release tag
- ✅ Signed: Part of SLSA Level 3 attested artifacts
Transparency:
- ✅ Public Access: Documentation on GitHub Pages
- ✅ Evidence-Based: Generated from actual code and tests
- ✅ Real-Time: Updated with every release
- ✅ Comprehensive: API, coverage, E2E, all in one place
Compliance:
- ✅ ISMS §3.2: Architecture documentation requirements met
- ✅ ISO 27001 A.12.1.1: Documented operating procedures
- ✅ Audit Trail: Full documentation history in git
- ✅ Evidence: Automated generation eliminates documentation drift
| 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 |
- Policy: Secure Development Policy §3.2 - Architecture Documentation
- Workflow: release.yml lines 92-155
- Documentation Hub: docs/index.html
- Process Guide: docs/RELEASE_PROCESS.md
- Attestations: GitHub Attestations
See FUTURE_WORKFLOWS.md for planned documentation improvements:
- Automated architecture diagram generation
- Interactive documentation search
- Documentation versioning (per release)
- PDF export for compliance reports
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:
- ✅ Minimal Attack Surface: Static content, no databases, no server-side execution
- ✅ Automated Security: CodeQL, Dependabot, npm audit prevent vulnerabilities
- ✅ Supply Chain Security: SHA-pinned actions, minimal dependencies, SBOM generation
- ✅ Data Integrity: Input validation, HTML sanitization, CSP enforcement
- ✅ Compliance: ISO 27001, GDPR, NIS2, EU CRA aligned
- ✅ Transparency: Public code, public security advisories, ISMS framework
Residual Risks:
- Medium: Data integrity (manual review not automated) - Addressed in Q3 2026
- Low: Supply chain attacks - Mitigated by minimal dependencies and Dependabot
- Low: Repository compromise - Mitigated by branch protection and code review
Future Enhancements:
- See FUTURE_SECURITY_ARCHITECTURE.md for roadmap
Document Approval:
| Role | Name | Date | Signature |
|---|---|---|---|
| CEO (Document Owner) | [Name] | 2026-04-20 | [Electronic] |
| CISO | [Name] | 2026-04-20 | [Electronic] |
Next Review Date: 2027-04-20
This document is maintained as part of Hack23 AB's Information Security Management System (ISMS)
ISMS Framework: Hack23/ISMS-PUBLIC