![]()
๐ Defense-in-Depth Protection for Swedish Parliament Transparency
๐ฏ Comprehensive Security Framework for Political Intelligence Platform
๐ Document Owner: CEO | ๐ Version: 2.5 | ๐
Last Updated: 2026-06-02 (UTC)
๐ Review Cycle: Annual | โฐ Next Review: 2027-06-02
๐ข Owner: Hack23 AB (Org.nr 5595347807) | ๐ท๏ธ Classification: Public
| Document | Focus | Description |
|---|---|---|
| Security Architecture | ๐ก๏ธ Security | Current document โ Defense-in-depth controls |
| Threat Model | ๐ฏ Threats | STRIDE/MITRE ATT&CK analysis |
| Future Security Architecture | ๐ Security Roadmap | Planned security improvements |
| Architecture | ๐๏ธ C4 Models | System structure and components |
| Data Model | ๐ Data | Entities, schemas, relationships |
| Flowcharts | ๐ Processes | Process flows and pipelines |
| State Diagrams | ๐ Behavior | System state transitions |
| Mindmaps | ๐บ๏ธ Concepts | Conceptual system maps |
| SWOT Analysis | ๐ผ Strategy | Strategic position assessment |
| Future Architecture | ๐ Architecture | Architectural evolution roadmap |
| Future Data Model | ๐ Data | Enhanced data architecture |
| Future Flowcharts | ๐ Processes | Improved process workflows |
| Future State Diagrams | ๐ Behavior | Advanced state management |
| Future Mindmaps | ๐ Concepts | Capability expansion maps |
| Future SWOT | ๐ Strategy | Future strategic opportunities |
| Workflows | ๐ง DevOps | CI/CD automation and pipelines |
| CRA Assessment | โ๏ธ Compliance | EU Cyber Resilience Act conformity |
| Policy | Focus | Link |
|---|---|---|
| Secure Development Policy | SDLC security, architecture requirements | Secure_Development_Policy.md |
| Open Source Policy | OSS governance, license compliance | Open_Source_Policy.md |
| CRA Conformity Assessment Process | CRA self-assessment template | CRA_Conformity_Assessment_Process.md |
| Threat Modeling Policy | STRIDE/MITRE ATT&CK methodology | Threat_Modeling.md |
| Classification Framework | CIA triad, RTO/RPO | CLASSIFICATION.md |
| gh-aw Architecture | Three-layer agentic workflow security model | gh-aw Architecture |
Riksdagsmonitor is a web platform providing Swedish Parliament intelligence and election monitoring capabilities. This document outlines the security architecture aligned with Hack23 AB's Information Security Management System (ISMS), Classification Framework, and compliance frameworks (ISO 27001, NIST CSF 2.0, CIS Controls v8.1).
Security Posture: Defense-in-depth architecture with dual-deployment (AWS CloudFront/S3 multi-region primary, GitHub Pages disaster recovery), HTTPS-only access, comprehensive CI/CD security controls, and SLSA Build Provenance attestations.
For complete CI/CD workflow documentation, see WORKFLOWS.md.
Riksdagsmonitor security architecture is governed by and aligned with Hack23 AB's comprehensive Information Security Management System (ISMS). This ensures consistent security practices across all organizational assets.
| Policy Document | Purpose | Application to Riksdagsmonitor |
|---|---|---|
| Information Security Policy | Organization-wide security governance | Establishes security objectives, risk management framework, and accountability |
| Secure Development Policy | Secure SDLC requirements | Mandates security documentation (SECURITY_ARCHITECTURE.md, THREAT_MODEL.md, FUTURE_SECURITY_ARCHITECTURE.md), code scanning, vulnerability management |
| Classification Framework | Information classification scheme | Defines handling requirements for Public/Internal/Confidential/Restricted data (see ยง2.3) |
| Incident Response Policy | Security incident procedures | Provides escalation paths, response team structure, lessons learned process (see ยง2.7) |
| Access Control Policy | Identity and access management | Defines MFA requirements, least privilege principles, access review cycles (see ยง2.1) |
Policy Review Cycle: All referenced policies reviewed annually by CISO. Next ISMS policy review: 2027-01-31.
Purpose:
Scope:
IntersectionObserver (Chart.js, D3.js)AWS Infrastructure Security (Primary Deployment):
๐ Authentication & Access Control:
๐ Audit Logging & Monitoring:
๐ Data Protection:
๐ก๏ธ DDoS & Threat Protection:
graph TB
User[User Browser]
Route53[AWS Route 53<br/>DNS + Health Checks]
subgraph "Primary: AWS Infrastructure"
CF[CloudFront CDN<br/>600+ Edge Locations]
S3US[S3 Bucket us-east-1<br/>Primary Storage + Versioning]
S3EU[S3 Bucket eu-west-1<br/>Cross-region Replica<br/>Active Failover Origin]
end
subgraph "Disaster Recovery: GitHub"
GHCDN[GitHub Pages CDN<br/>Standby Deployment]
end
subgraph "GitHub Infrastructure"
GitHubRepo[GitHub Repository<br/>main branch]
Actions[GitHub Actions<br/>CI/CD Dual Deploy]
Security[Security Scanning<br/>Dependabot, CodeQL, Secrets]
end
CIA[CIA Platform<br/>www.hack23.com/cia]
User -->|DNS Query| Route53
Route53 -->|DNS Response: CloudFront Primary| User
Route53 -.->|DNS Response: GitHub Pages on Failover| User
User -->|HTTPS Only TLS 1.3| CF
User -.->|HTTPS Only TLS 1.3 (DR)| GHCDN
CF -->|Cache Miss| S3US
CF -.->|Origin Failover on 5xx errors| S3EU
S3US -->|Async Cross-Region Replication (<15 min RPO)| S3EU
User -->|External Links| CIA
GHCDN --> GitHubRepo
Actions -->|Deploy| S3US
Actions -->|Deploy| GitHubRepo
Security -->|Monitor| GitHubRepo
style User fill:#e1f5ff,color:#000000
style Route53 fill:#ff9800,color:#000000
style CF fill:#4caf50,color:#000000
style S3US fill:#2196f3,color:#ffffff
style GHCDN fill:#90caf9,color:#000000
style Actions fill:#ff9800,color:#000000
style Security fill:#f44336,color:#ffffff
style CIA fill:#9c27b0,color:#ffffff
Public Access Model:
Control Mapping:
GitHub Repository Permissions:
CI/CD Pipeline Permissions:
Control Mapping:
Information Classification:
Following Hack23 AB ISMS information classification policy:
| Classification | Data Types | Handling Requirements | Storage / Access Method |
|---|---|---|---|
| ๐ข Public | Website content, Swedish Riksdag open data, documentation | No restrictions, TLS 1.3 in transit | GitHub repository, AWS S3, GitHub Pages (CDN) |
| ๐ก Internal | GitHub Actions secrets, AWS credentials, deployment configs | Encrypted at rest, MFA access, least privilege | GitHub Secrets, AWS IAM (ephemeral STS/OIDC) |
| ๐ Confidential | Not applicable | N/A | N/A |
| ๐ด Restricted | Not applicable | N/A | N/A |
Data Inventory:
Data Protection Controls:
In Transit:
At Rest:
Access Controls:
Data Lifecycle:
Control Mapping:
AWS CloudFront Infrastructure (Primary):
GitHub Pages Infrastructure (Disaster Recovery):
Security Headers (Target Configuration - AWS CloudFront Response Headers Policy):
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src 'self' fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://raw.githubusercontent.com
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Note: CSP style-src includes 'unsafe-inline' for Chart.js/D3.js inline styles; script-src uses 'self' plus per-script sha256 hashes for the small bootstrap snippets (no 'unsafe-inline' for scripts). The connect-src directive includes https://raw.githubusercontent.com to allow fetching CIA CSV data from the cia repository. Security headers are configured via AWS CloudFront Response Headers Policy for the primary deployment. GitHub Pages disaster recovery inherits default GitHub Pages security headers. Chart.js, D3.js, chartjs-plugin-annotation and Mermaid are hosted locally on CloudFront (js/lib/) rather than via external CDN, eliminating external script dependencies (CI-enforced by tests/no-external-cdn.test.ts).
Control Mapping:
Web Application Security:
src/browser/dashboards/, bundled by Vite into hashed ES modules and lazy-loaded on demand via an IntersectionObserver โ each module's import() fires only when its container scrolls into viewsrc/browser/main.ts) registers 11 specialised dashboards; the CIA Intelligence Dashboard page (dashboard/index*.html) is orchestrated by src/browser/cia/dashboard-init.ts.github/workflows/validate-cia-data.yml); validation failures currently surface as warnings rather than blocking publication, and client-side code then parses this CSV (D3 CSV utilities/custom parsers) and applies basic sanity checks prior to rendering via Chart.js/D3.jshttps://raw.githubusercontent.com/Hack23/cia/ that is subject to non-blocking CI schema validation checks in pre-processing (e.g., .github/workflows/validate-cia-data.yml), with local caching for performance; the browser consumes this dataset which may contain validation warningsDashboard Security:
src/browser/dashboards/committees-dashboard.ts) โ
src/browser/dashboards/coalition-dashboard.ts + coalition-loader.ts) โ
src/browser/dashboards/election-cycle.ts) โ
src/browser/dashboards/risk-dashboard.ts) โ
src/browser/dashboards/anomaly-detection.ts โ standalone timeline, Z-score distribution, type, and quarterly-frequency charts) โ
src/browser/dashboards/party-dashboard.ts) โ
src/browser/dashboards/seasonal-patterns.ts) โ
src/browser/dashboards/pre-election.ts) โ
src/browser/dashboards/ministry-dashboard.ts) โ
src/browser/dashboards/politician-dashboard.ts) โ
Dependency Management:
.github/dependabot.yml) and automated dependency risk assessment for repository-managed components via GitHub dependency-review and Dependabot alertsControl Mapping:
The news-generation pipeline (scripts/aggregate-analysis.ts โ scripts/render-articles.ts โ scripts/render-lib/) produces HTML articles from AI-authored markdown artifacts under analysis/daily/$DATE/$SUB/. The AI-authored markdown is an untrusted input from the perspective of the renderer; the sanitisation chain is therefore a primary output-encoding control for the platform.
analysis/daily/$DATE/$SUB/*.md (untrusted AI authored markdown)
โ
โผ
gray-matter frontmatter extraction (structural only โ no HTML)
โ
โผ
unified + remark-parse + remark-gfm (markdown โ MDAST)
โ
โผ
remark-rehype + rehype-raw (MDAST โ HAST; raw HTML islands preserved)
โ
โผ
rehype-sanitize โโโโ TRUST BOUNDARY (allow-list enforcement)
โ
โผ
rehype-slug + rehype-autolink-headings (stable anchors for TOC)
โ
โผ
rehype-stringify (HAST โ serialised HTML)
โ
โผ
scripts/render-lib/chrome.ts (JSON-LD NewsArticle, SEO, lang switcher)
โ
โผ
news/$DATE-$SUB-{en,sv}.html (trusted output)
rehype-sanitize allow-listThe sanitiser is configured with an explicit allow-list (schema) rather than a blocklist. Only these elements and attributes survive the boundary:
| Category | Allowed | Rationale |
|---|---|---|
| Block text | p, h1โh6, blockquote, pre, hr | Standard article structure |
| Inline text | `a[href | title |
| Lists | ul, ol, li | Markdown lists |
| Tables | table, thead, tbody, tr, th[scope], td, caption | GFM tables (accessibility-aware) |
| Images | `img[src | alt |
| Figures | figure, figcaption | Diagram captions and accessible text equivalents |
| Disclosure | details, summary | Mermaid diagram source fallback (WCAG 2.1 AA text equivalent) |
| Extension | pre.mermaid | Client-side Mermaid rendering โ see below |
URL-bearing attributes (href, src) are filtered to the following schemes: http:, https:, mailto:, plus data:image/{png,jpeg,gif,webp,svg+xml} for embedded images only. Rejected: javascript:, vbscript:, non-image data:, file:, chrome:, and all other URI schemes.
Explicitly rejected elements (removed without error so AI-authored content cannot escape the sandbox): script, iframe, object, embed, form, input, button, style, link, meta, base, applet, frame, frameset, and every on* event handler attribute.
Mermaid diagrams are the only HTML extension permitted past the sanitiser. They are handled as follows:
```mermaid fenced block in the .md artifact is passed through by remark-parse as a code node with lang: mermaid.<pre class="mermaid">โฆsourceโฆ</pre> so the sanitiser's pre[class|lang] rule lets it through.<figure> with a <figcaption> and a <details>-wrapped plain-text fallback containing the source (WCAG 2.1 AA text equivalent).scripts/render-lib/chrome.ts conditionally injects <script type="module" src="/js/lib/mermaid-init.mjs"></script> only when at least one <pre class="mermaid"> survived sanitisation.mermaid-init.mjs imports Mermaid via native ESM dynamic import() and calls mermaid.initialize({ startOnLoad: false, securityLevel: 'strict' }). securityLevel: 'strict' disables Mermaid's own click-handler and interaction features, so a malicious Mermaid diagram cannot execute JavaScript even if the DSL is exploited.'unsafe-eval'. Mermaid's strict-mode parser does not require eval; this has been validated and is documented in the deployment runbook.The trust boundary is therefore: AI โ markdown โ Mermaid DSL โ SVG โ never AI โ JavaScript.
Relative markdown links inside aggregated artifacts (e.g. [methodology](../methodologies/devils-advocate.md)) would resolve against news/ in the published output and 404. The aggregator rewrites every relative .md, .json, and .html link to an absolute https://github.com/Hack23/riksdagsmonitor/blob/main/โฆ URL before the sanitiser sees them. This is an output-encoding control: it removes a broken-link class and pins every citation to a content-addressable GitHub blob URL that serves as the provenance chain.
The aggregator emits a .manifest.json sibling to each article.md listing every source artifact consumed, with a SHA-256 digest:
{
"article": "analysis/daily/2026-04-24/propositions/article.md",
"generated_at": "2026-04-24T04:12:31Z",
"sources": [
{ "path": "analysis/daily/2026-04-24/propositions/executive-brief.md", "sha256": "โฆ" },
{ "path": "analysis/daily/2026-04-24/propositions/synthesis.md", "sha256": "โฆ" },
{ "path": "analysis/methodologies/devils-advocate.md", "sha256": "โฆ" }
]
}
The renderer emits the manifest contents into the NewsArticle.citation[] JSON-LD block, giving downstream consumers a cryptographic evidence chain: every claim in the HTML can be traced back to a specific SHA-256 of a specific markdown artifact at a specific timestamp.
Control Mapping:
unified/remark/rehype/gray-matter are vetted, pinned, and Dependabot-groupedSecurity Monitoring:
Audit Logging:
Alert Mechanisms:
Control Mapping:
Security Incident Procedures:
Incident Response Team:
Control Mapping:
SLSA Build Provenance Attestations:
actions/attest-build-provenance@v3.2.0)gh attestation verify riksdagsmonitor-vX.Y.Z.zip -R Hack23/riksdagsmonitorSoftware Bill of Materials (SBOM):
anchore/sbom-action@v0.22.2)actions/attest-sbom@v3.0.0)package.json x-external-mcp field records MCP servers outside the npm graph (Python, Docker, HTTP). It is currently empty โ all economic-data clients (World Bank, SCB, IMF) ship as npm TypeScript (scripts/world-bank-client.ts, scripts/scb-client.ts, scripts/imf-client.ts) and are fully covered by the standard SPDX SBOM; see THREAT_MODEL.md TB-6a for the IMF client's threat model.External Data Providers (parity across the three primary economic sources):
| Provider | Integration | Transport / Hosts | Classification | Controls |
|---|---|---|---|---|
| SCB (Statistics Sweden) | scb-mcp (local @jarib/pxweb-mcp@2.0.0) | HTTPS (TLS 1.3) โ api.scb.se/OV0104/v2beta | Public | Egress allowlist; MCP tool allow-list; graceful fallback; no auth |
| World Bank | world-bank-mcp (local worldbank-mcp@1.0.1) + scripts/world-bank-client.ts | HTTPS (TLS 1.3) โ data.worldbank.org, api.worldbank.org | Public | Egress allowlist; npm SBOM coverage; response schema validation; no auth |
| IMF (new โ ADR 0001) | Pure-TypeScript client scripts/imf-client.ts (not MCP) | HTTPS (TLS 1.3) โ data.imf.org, api.imf.org, www.imf.org (Datamapper JSON + SDMX 3.0) | Public | Egress allowlist; npm SBOM coverage; DatamapperResponse schema + finite-numeric + year parse-guard validation; .meta.json tamper-evident cache sidecars under analysis/data/imf/; 3ร exponential back-off for rate-limit; graceful fallback; no auth |
All three providers share: GitHub-runner root CA trust anchors, public-data classification, no API key, and optional-enrichment semantics (failure never blocks article generation or site availability).
Release Pipeline Security (3-job workflow):
Prepare Job (15-20min):
Build Job (5min):
Release Job (5-10min):
Release Artifacts (per version):
riksdagsmonitor-vX.Y.Z.zip - Production buildriksdagsmonitor-vX.Y.Z.zip.sha256 - Integrity checksumriksdagsmonitor-vX.Y.Z.spdx.json - SBOMriksdagsmonitor-vX.Y.Z.zip.intoto.jsonl - Build provenance attestationriksdagsmonitor-vX.Y.Z.spdx.json.intoto.jsonl - SBOM attestationDocumentation as Code: All technical reports automatically generated and committed to docs/ on each release:
docs/api/ - JSDoc API documentationdocs/coverage/ - Vitest test coverage (HTML + lcov)docs/test-results/ - Vitest test results (JSON + HTML)docs/cypress/ - Cypress E2E test reportsdocs/dependencies/ - npm dependency tree (JSON + TXT)docs/index.html - Documentation hub (cyberpunk-themed)Verification Procedures:
# Verify build provenance attestation
gh attestation verify riksdagsmonitor-vX.Y.Z.zip -R Hack23/riksdagsmonitor
# Verify SBOM attestation
gh attestation verify riksdagsmonitor-vX.Y.Z.spdx.json -R Hack23/riksdagsmonitor
# Verify artifact integrity
sha256sum -c riksdagsmonitor-vX.Y.Z.zip.sha256
Control Mapping:
For complete release process documentation, see RELEASE_PROCESS.md and WORKFLOWS.md.
| Control | Implementation | Status |
|---|---|---|
| A.8.2 | Information classification scheme, data inventory, handling controls | โ Implemented |
| A.9.2 | GitHub MFA, SSH keys, GPG signing | โ Implemented |
| A.9.4 | Repository permissions, least privilege | โ Implemented |
| A.10.1 | TLS 1.3, HTTPS-only, encryption at rest | โ Implemented |
| A.12.4 | Git history, GitHub audit logs, AWS CloudTrail | โ Implemented |
| A.13.1 | AWS infrastructure, security headers | โ Implemented |
| A.14.2 | Dependabot, CodeQL scanning | โ Implemented |
| A.16.1 | Incident response procedures | โ Implemented |
| Function | Category | Implementation |
|---|---|---|
| GOVERN | Asset Management | Information classification scheme, data inventory |
| IDENTIFY | Asset Management | GitHub repository, static assets, data sources |
| PROTECT | Access Control | GitHub authentication, MFA, AWS OIDC |
| PROTECT | Data Security | TLS 1.3, HTTPS-only, encryption at rest |
| DETECT | Security Monitoring | Dependabot, CodeQL, secret scanning |
| RESPOND | Incident Response | Documented procedures, escalation paths |
| RECOVER | Recovery Planning | Git rollback, S3 versioning, multi-region replication |
| IG | Control | Implementation |
|---|---|---|
| IG1 | 3.1 Establish Data Management | Information classification policy, data inventory |
| IG1 | 3.10 Encrypt Data in Transit | TLS 1.3, HTTPS-only |
| IG1 | 5.1 Account Inventory | GitHub organization audit |
| IG1 | 8.2 Collect Audit Logs | Git history, GitHub Actions logs, AWS CloudTrail |
| IG2 | 6.8 Role-Based Access Control | GitHub repository permissions, AWS IAM |
| IG2 | 13.1 Security Event Alerting | GitHub security alerts, AWS CloudWatch |
| IG2 | 16.1 Secure Development | Static site with reduced injection surface; mitigated via CSP/SRI/safe DOM handling; secure CI/CD |
Access Control:
Network Security:
Development Security:
Security Monitoring:
Quality Checks:
Incident Response:
Patch Management:
AWS Infrastructure Limitations:
GitHub Pages Limitations (DR):
Client-Side JavaScript Limitations:
'unsafe-inline' needed for Chart.js/D3.js| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| AWS CloudFront/S3 Outage | Low | Medium | GitHub Pages DR, documented failover |
| GitHub Platform Outage (DR) | Low | Low | AWS primary handles traffic |
| DDoS Attack on AWS | Low | Low | AWS Shield Standard, CloudFront protection |
| XSS via Chart.js/D3.js | Low | Medium | CSP headers, locally-hosted libraries (no external CDN), quarterly version reviews |
| Compromised GitHub Account | Low | High | MFA, SSH keys, GPG signing |
| Chart.js/D3.js Vulnerability | Medium | Medium | Locally-hosted libraries with quarterly/CVE version reviews, deployment-time integrity verification, rapid version updates |
| CIA Data Injection | Low | Medium | Schema validation, local CSV caching |
| Content Defacement | Low | Medium | Git rollback, branch protection, dual deployment |
| DNS Hijacking via Route 53 | Very Low | High | DNSSEC (planned), IAM least privilege |
| Role | Responsibility |
|---|---|
| Security Architect | Overall security architecture and compliance |
| Repository Owners | Access control, security monitoring |
| Contributors | Secure coding practices, MFA compliance |
| CISO (James Pether Sรถrling) | ISMS oversight, incident escalation |
| Role | Name | Date | Signature |
|---|---|---|---|
| Security Architect | James Pether Sรถrling, CISSP, CISM | 2026-02-10 | [Digital Signature] |
| Repository Owner | Hack23 AB | 2026-02-10 | [Approved via Git Commit] |
Riksdagsmonitor implements a comprehensive defense-in-depth security strategy with six overlapping layers of protection. Each layer provides independent security controls, ensuring that compromise of a single layer does not result in complete system failure.
graph TB
subgraph "Layer 6: Monitoring & Response"
L6A[GitHub Security Alerts]
L6B[AWS CloudWatch]
L6C[Dependabot Monitoring]
L6D[Incident Response Team]
end
subgraph "Layer 5: CI/CD Security"
L5A[CodeQL SAST]
L5B[Dependabot Updates]
L5C[Secret Scanning]
L5D[SLSA Attestations]
L5E[step-security/harden-runner]
end
subgraph "Layer 4: Data Protection"
L4A[TLS 1.3 Transit]
L4B[AES-256 At Rest]
L4C[S3 Versioning]
L4D[Cross-Region Replication]
end
subgraph "Layer 3: Access Control"
L3A[GitHub MFA]
L3B[SSH Keys + Passphrase]
L3C[GPG Commit Signing]
L3D[AWS OIDC ephemeral credentials]
end
subgraph "Layer 2: Application Security"
L2A[Content Security Policy]
L2B[HSTS Headers]
L2C[Subresource Integrity]
L2D[XSS Protection]
end
subgraph "Layer 1: Network Security"
L1A[AWS CloudFront CDN]
L1B[AWS Shield Standard]
L1C[AWS WAF on CloudFront (planned)]
L1D[GitHub Infrastructure DR]
end
User[๐ค User/Attacker] --> L1A
User -.->|DR Failover| L1D
L1A --> L2A
L2A --> L3A
L3A --> L4A
L4A --> L5A
L5A --> L6A
style User fill:#ff6b6b,color:#000000
style L1A fill:#51cf66,color:#000000
style L2A fill:#4dabf7,color:#000000
style L3A fill:#ffd43b,color:#000000
style L4A fill:#ff8787,color:#000000
style L5A fill:#da77f2,color:#000000
style L6A fill:#20c997,color:#000000
Purpose: Protect against network-level attacks (DDoS, volumetric attacks, malicious traffic).
| Control | Technology | Purpose | Status |
|---|---|---|---|
| CDN Protection | AWS CloudFront (600+ edge locations) | Distribute traffic, absorb attacks | โ Active |
| DDoS Mitigation | AWS Shield Standard | Automatic protection against common attacks | โ Active |
| DNS Protection | AWS Route 53 with health checks | Prevent DNS-based attacks, enable failover | โ Active |
| Geographic Filtering | CloudFront geo-restrictions capability | Block traffic from high-risk regions (configurable) | ๐ง Available |
| Rate Limiting | AWS WAF (planned 2027 Q2) | Prevent abuse, scraping, brute force | ๐ Roadmap |
| DR Infrastructure | GitHub Pages CDN | Independent infrastructure for resilience | โ Active |
ISO 27001: A.13.1 (Network Security Management)
NIST CSF 2.0: PR.AC-5 (Network integrity protected)
CIS Controls v8.1: 13.1 (Centralize security event alerting)
Purpose: Protect against web application attacks (XSS, clickjacking, MIME sniffing).
| Control | Implementation | Purpose | Status |
|---|---|---|---|
| Content Security Policy | default-src 'self'; script-src 'self' 'unsafe-inline' | Mitigate XSS attacks | โ Active |
| HTTP Strict Transport Security | max-age=31536000; includeSubDomains | Enforce HTTPS-only | โ Active |
| X-Frame-Options | DENY | Prevent clickjacking | โ Active |
| X-Content-Type-Options | nosniff | Prevent MIME sniffing | โ Active |
| Referrer Policy | strict-origin-when-cross-origin | Control referrer information | โ Active |
| Permissions Policy | Disable geolocation, microphone, camera | Minimize browser permissions | โ Active |
| Subresource Integrity | Planned: SHA-384 hashes for third-party/CDN assets and critical local libraries | Verify resource integrity | ๐ Planned |
Note: CSP style-src includes 'unsafe-inline' for Chart.js/D3.js inline styles; script-src uses 'self' plus per-script sha256 hashes (no 'unsafe-inline' for scripts).
ISO 27001: A.14.2 (Security in development and support)
NIST CSF 2.0: PR.IP-12 (Vulnerability management plan)
CIS Controls v8.1: 16.1 (Secure application development process)
Purpose: Ensure only authorized entities can modify code or infrastructure.
| Control | Implementation | Scope | Status |
|---|---|---|---|
| Multi-Factor Authentication | GitHub MFA mandatory | All contributors | โ Enforced |
| SSH Key Authentication | Passphrase-protected keys | Git operations | โ Enforced |
| GPG Commit Signing | Verified commits required | All commits to main | โ Enforced |
| AWS OIDC | Ephemeral credentials (no long-lived keys) | CI/CD AWS deployments | โ Active |
| Branch Protection | Require reviews, status checks | main branch | โ Active |
| Least Privilege IAM | Minimal S3/CloudFront permissions | AWS resources | โ Active |
| Repository Permissions | RBAC: Admin/Write/Read roles | GitHub access | โ Active |
ISO 27001: A.9.2 (User access management), A.9.4 (System access control)
NIST CSF 2.0: PR.AC-1 (Identities and credentials managed), PR.AC-4 (Access permissions managed)
CIS Controls v8.1: 5.1 (Account inventory), 6.8 (Role-based access control)
Purpose: Protect data in transit and at rest; enable recovery from data loss.
| Control | Technology | Scope | Status |
|---|---|---|---|
| TLS 1.3 Encryption | AWS CloudFront + GitHub Pages | All traffic in transit | โ Active |
| AES-256 Encryption | S3 server-side encryption | Data at rest (S3) | โ Active |
| S3 Versioning | Enabled on all buckets | Rollback capability | โ Active |
| Cross-Region Replication | us-east-1 โ eu-west-1 (<15 min) | Disaster recovery, data durability | โ Active |
| GitHub Secrets Encryption | Libsodium sealed boxes | CI/CD secrets | โ Active |
| Immutable Git History | Cryptographic commit chain | Audit trail | โ Active |
| GPG Signing | Verified commits | Commit integrity | โ Active |
RPO (Recovery Point Objective): <15 minutes (S3 cross-region replication)
RTO (Recovery Time Objective): <15 minutes (AWS primary), <30 minutes (GitHub Pages DR)
ISO 27001: A.10.1 (Cryptographic controls)
NIST CSF 2.0: PR.DS-1 (Data-at-rest protected), PR.DS-2 (Data-in-transit protected)
CIS Controls v8.1: 3.10 (Encrypt data in transit)
Purpose: Prevent introduction of vulnerabilities during development and deployment.
| Control | Tool | Frequency | Status |
|---|---|---|---|
| SAST Scanning | CodeQL | Every PR | โ Active |
| Dependency Scanning | Dependabot | Daily | โ Active |
| Secret Scanning | GitHub Secret Scanning | Every push | โ Active |
| SLSA Attestations | GitHub Attestations (Build Provenance + SBOM) | Every release | โ Active |
| Workflow Hardening | step-security/harden-runner | Every workflow run | โ Active |
| SBOM Generation | Anchore SBOM Action (SPDX format) | Every release | โ Active |
| Automated Updates | Dependabot PRs | Weekly | โ Active |
| Code Review | Required reviewers | Every PR | โ Active |
Supply Chain Security Level: SLSA Level 2+ (cryptographically signed build provenance)
ISO 27001: A.8.30 (Secure coding), A.8.32 (Change management), A.14.2 (Security in development)
NIST CSF 2.0: PR.DS-6 (Integrity verification), ID.SC-3 (Supply chain risk assessment)
CIS Controls v8.1: 16.6 (Application software security), 16.10 (Vulnerability remediation)
Purpose: Detect security events, respond to incidents, and continuously improve security posture.
| Control | Tool | Detection Type | Status |
|---|---|---|---|
| Security Alerts | GitHub Security Advisories | CVE notifications | โ Active |
| Dependency Alerts | Dependabot | Vulnerable dependencies | โ Active |
| Code Vulnerabilities | CodeQL | SAST findings | โ Active |
| Secret Exposure | GitHub Secret Scanning | Leaked credentials | โ Active |
| Infrastructure Monitoring | AWS CloudWatch | Performance & availability | โ Active |
| Audit Logging | GitHub Audit Log + AWS CloudTrail | Access & change tracking | โ Active |
| Incident Response | Documented procedures (ยง2.7) | Security event handling | โ Active |
Mean Time to Detect (MTTD): <24 hours (automated scanning)
Mean Time to Respond (MTTR): Critical: 24h, High: 7d, Medium: 30d, Low: 90d (see ยงVulnerability Management)
ISO 27001: A.12.4 (Logging and monitoring), A.16.1 (Incident management)
NIST CSF 2.0: DE.CM-1 (Network monitored), RS.CO-1 (Personnel know roles)
CIS Controls v8.1: 8.2 (Collect audit logs), 17.1 (Designate incident handling personnel)
Riksdagsmonitor maintains comprehensive data integrity controls and immutable audit trails to ensure trustworthiness of all content and changes.
| Mechanism | Implementation | Purpose | Status |
|---|---|---|---|
| GPG Commit Signing | All commits to main branch must be signed | Verify author identity | โ Enforced |
| Verified Commits | GitHub "Verified" badge on signed commits | Visual indicator of authenticity | โ Active |
| Cryptographic Chain | SHA-256 commit hashes form immutable chain | Prevent history tampering | โ Active |
| Branch Protection | Require signed commits for main | Policy enforcement | โ Active |
Verification Command:
git log --show-signature main
# or verify specific commit:
git verify-commit <commit-sha>
Framework: SLSA (Supply Chain Levels for Software Artifacts) Level 2+
Purpose: Cryptographically prove artifacts were built by trusted CI/CD pipeline without tampering
| Artifact | Attestation Type | Verification Command |
|---|---|---|
riksdagsmonitor-vX.Y.Z.zip | Build Provenance | gh attestation verify riksdagsmonitor-vX.Y.Z.zip -R Hack23/riksdagsmonitor |
riksdagsmonitor-vX.Y.Z.spdx.json | SBOM Attestation | gh attestation verify riksdagsmonitor-vX.Y.Z.spdx.json -R Hack23/riksdagsmonitor |
Attestation Format: in-toto (*.intoto.jsonl) - industry-standard supply chain metadata format
What SLSA Attestations Prove:
| Log Source | Retention | Scope | Access |
|---|---|---|---|
| Git Commit History | Permanent | All code/content changes | Public (GitHub) |
| GitHub Audit Log | 90 days (free), 180 days (Enterprise) | Org access, permission changes | Org admins |
| GitHub Actions Logs | 90 days | CI/CD workflow execution | Repo admins |
| AWS CloudTrail | 90 days | API calls, IAM actions, S3 operations | AWS account admins |
| AWS CloudFront Access Logs | 90 days | HTTP requests, errors, traffic patterns | AWS account admins |
SHA-256 Checksums: Every release includes .sha256 file for artifact integrity verification
# Verify artifact integrity
sha256sum -c riksdagsmonitor-vX.Y.Z.zip.sha256
SBOM Integrity: Software Bill of Materials (SPDX format) cryptographically signed with SLSA attestation
ISO 27001: A.12.4 (Logging and monitoring), A.8.32 (Change management)
NIST CSF 2.0: PR.DS-6 (Integrity checking mechanisms)
CIS Controls v8.1: 8.2 (Collect audit logs), 8.5 (Collect detailed audit logs)
Riksdagsmonitor implements continuous security monitoring with automated alerting and response workflows.
| Feature | Detection Scope | Alert Mechanism | Auto-Remediation |
|---|---|---|---|
| Dependabot Alerts | npm/GitHub Actions dependency vulnerabilities | Email + GitHub UI | Automated PRs for patches |
| Secret Scanning | Hardcoded credentials, API keys, tokens | Email + GitHub UI + Block push | Manual rotation required |
| CodeQL Scanning | SAST vulnerabilities (CWE-top 25) | PR checks + GitHub UI | Manual code fix required |
| Security Advisories | CVEs affecting repository | Email + GitHub UI | Review + response |
| Severity | CVSS Score | Response SLA | Notification | Auto-Actions |
|---|---|---|---|---|
| Critical | 9.0-10.0 | 24 hours | Email + Slack | Dependabot PR (if available) |
| High | 7.0-8.9 | 7 days | Email + Slack | Dependabot PR (if available) |
| Medium | 4.0-6.9 | 30 days | Email weekly digest | Dependabot PR (if available) |
| Low | 0.1-3.9 | 90 days | Email monthly digest | Dependabot PR (if available) |
Metrics Monitored:
Alerting Thresholds:
Event Types Tracked:
Correlation Analysis:
ISO 27001: A.12.4 (Logging and monitoring), A.16.1 (Incident management)
NIST CSF 2.0: DE.CM-1 (Network monitored), DE.AE-3 (Event data aggregated and analyzed)
CIS Controls v8.1: 8.2 (Collect audit logs), 13.1 (Centralize security event alerting)
Riksdagsmonitor implements dual-deployment architecture with automatic failover to achieve 99.9%+ availability SLA.
graph TB
User[๐ค User Request]
subgraph "DNS Layer"
Route53[AWS Route 53<br/>Health Checks + Failover]
end
subgraph "Primary Deployment - AWS"
CF[CloudFront CDN<br/>600+ Edge Locations<br/>SLA: 99.9%]
S3US[S3 us-east-1<br/>Primary Origin<br/>SLA: 99.99%]
S3EU[S3 eu-west-1<br/>Failover Origin<br/>SLA: 99.99%]
CF -->|Cache Miss| S3US
CF -.->|Origin Failover<br/>on 5xx errors| S3EU
S3US -.->|Async Replication<br/>RPO: <15 min| S3EU
end
subgraph "Disaster Recovery - GitHub"
GHCDN[GitHub Pages CDN<br/>SLA: 99.9%]
GHRepo[GitHub Repository<br/>main branch]
GHCDN --> GHRepo
end
User --> Route53
Route53 -->|Primary DNS| CF
Route53 -.->|Failover DNS<br/>on health check failure| GHCDN
style User fill:#e1f5ff,color:#000000
style Route53 fill:#ff9800,color:#000000
style CF fill:#4caf50,color:#000000
style S3US fill:#2196f3,color:#ffffff
style S3EU fill:#90caf9,color:#000000
style GHCDN fill:#9c27b0,color:#ffffff
style GHRepo fill:#673ab7,color:#ffffff
| Component | SLA | Monthly Downtime | Redundancy | Status |
|---|---|---|---|---|
| AWS CloudFront | 99.9% | 43 minutes | 600+ edge locations | โ Primary |
| AWS S3 us-east-1 | 99.99% | 4.3 minutes | Multi-AZ, versioning | โ Primary |
| AWS S3 eu-west-1 | 99.99% | 4.3 minutes | Multi-AZ, versioning | โ Origin failover |
| GitHub Pages CDN | 99.9% | 43 minutes | Global CDN | โ DR failover |
| AWS Route 53 | 100% | 0 minutes (SLA) | Global anycast DNS | โ Active-active |
Composite Availability: 99.95%+ (accounting for dual-deployment failover)
| Failure Mode | Detection | Failover Mechanism | RTO | RPO | Status |
|---|---|---|---|---|---|
| CloudFront Edge Degradation | Automatic (CloudFront routing) | Route to nearest healthy edge | <1 second | 0 | โ Automatic |
| S3 us-east-1 Failure | CloudFront origin health (4xx/5xx) | CloudFront fails over to S3 eu-west-1 | <30 seconds | <15 min | โ Automatic |
| AWS Region Outage | Route 53 health checks (3 failures) | DNS failover to GitHub Pages | <5 minutes | <15 min | โ Automatic |
| AWS Platform Outage | Route 53 health checks (3 failures) | DNS failover to GitHub Pages | <5 minutes | <15 min | โ Automatic |
| GitHub Pages Degradation | Not applicable (DR only) | N/A (AWS is primary) | N/A | N/A | N/A |
| Metric | Target | Actual | Notes |
|---|---|---|---|
| RTO (Recovery Time Objective) | <15 minutes | <5 minutes (DNS failover) | Time to restore service availability |
| RPO (Recovery Point Objective) | <15 minutes | <15 minutes (S3 replication) | Maximum acceptable data loss |
| MTTR (Mean Time to Repair) | <2 hours | Varies by issue | Time to restore primary service |
| MTBF (Mean Time Between Failures) | >720 hours (30 days) | >2160 hours (90 days) | Based on 99.9% SLA |
Configuration:
Replication Monitoring:
Test Schedule:
Last DR Test: 2026-02-15 (GitHub Pages failover - Success, RTO: 4m 32s)
Next DR Test: 2026-05-15 (Full AWSโGitHub failover exercise)
ISO 27001: A.17.1 (Information security continuity), A.17.2 (Redundancies)
NIST CSF 2.0: RC.RP-1 (Recovery plan executed), RC.CO-3 (Recovery activities communicated)
CIS Controls v8.1: 11.1 (Establish and maintain data recovery), 11.5 (Establish and maintain an isolated recovery environment)
Riksdagsmonitor implements comprehensive threat detection capabilities with defined investigation workflows.
| Threat Category | Detection Method | Tools | Alert Severity | Status |
|---|---|---|---|---|
| Vulnerable Dependencies | Automated scanning | Dependabot | Critical/High/Medium/Low | โ Active |
| Code Vulnerabilities | SAST analysis | CodeQL (CWE-top 25) | High/Medium/Low | โ Active |
| Exposed Secrets | Pattern matching | GitHub Secret Scanning | Critical | โ Active |
| Supply Chain Attacks | SBOM analysis | Anchore + Dependabot | High | โ Active |
| Unauthorized Access | Authentication logs | GitHub Audit Log | Critical | โ Active |
| Infrastructure Anomalies | Metrics analysis | AWS CloudWatch | Medium | โ Active |
| DNS Hijacking | Health checks | Route 53 monitoring | Critical | โ Active |
| DDoS Attacks | Traffic analysis | AWS Shield Standard | High | โ Active |
graph TB
Alert[๐จ Security Alert Triggered]
Alert --> Triage{Triage<br/>Is it valid?}
Triage -->|False Positive| Dismiss[๐ Document & Dismiss<br/>Update detection rules]
Triage -->|Valid Threat| Assess{Assess<br/>Severity?}
Assess -->|Critical| Immediate[๐ด Immediate Response<br/>24h SLA]
Assess -->|High| Urgent[๐ Urgent Response<br/>7d SLA]
Assess -->|Medium| Scheduled[๐ก Scheduled Response<br/>30d SLA]
Assess -->|Low| Backlog[๐ข Backlog<br/>90d SLA]
Immediate --> Investigate
Urgent --> Investigate
Scheduled --> Investigate
Backlog --> Investigate
Investigate[๐ Investigate<br/>Scope & Impact] --> Contain[๐ก๏ธ Contain<br/>Limit damage]
Contain --> Remediate[๐ง Remediate<br/>Fix vulnerability]
Remediate --> Verify[โ
Verify<br/>Test fix]
Verify --> Document[๐ Document<br/>Lessons learned]
Document --> Close[โ๏ธ Close Alert<br/>Update docs]
Close --> Review{Requires<br/>Architecture Update?}
Review -->|Yes| UpdateDocs[๐ Update SECURITY_ARCHITECTURE.md<br/>and THREAT_MODEL.md]
Review -->|No| End[๐ End]
UpdateDocs --> End
Dismiss --> End
style Alert fill:#ff6b6b,color:#000000
style Immediate fill:#ff0000,color:#fff
style Urgent fill:#ff6b6b,color:#000000
style Scheduled fill:#ffd43b,color:#000000
style Backlog fill:#51cf66,color:#000000
style Contain fill:#4dabf7,color:#000000
style Remediate fill:#da77f2,color:#000000
style Verify fill:#20c997,color:#000000
style End fill:#e9ecef,color:#000000
1. Dependabot Vulnerability Alert
package.json / package-lock.jsonnpm audit, re-scan with Dependabot, test functionality2. CodeQL Code Scanning Alert
3. Secret Scanning Alert
4. Infrastructure Anomaly (AWS)
| Source | Type | Frequency | Purpose |
|---|---|---|---|
| GitHub Security Advisories | CVE database | Real-time | Dependency vulnerabilities |
| NIST NVD | CVE database | Daily | Vulnerability research |
| OWASP Top 10 | Best practices | Annual | Web application security |
| CWE Top 25 | Weakness patterns | Annual | Code review focus areas |
| AWS Security Bulletins | Infrastructure advisories | Real-time | AWS-specific threats |
| MITRE ATT&CK | Threat intelligence | Quarterly | Threat modeling (see THREAT_MODEL.md) |
ISO 27001: A.16.1 (Management of information security incidents), A.12.4 (Logging and monitoring)
NIST CSF 2.0: DE.AE-2 (Detected events analyzed), DE.AE-5 (Incident alert thresholds established)
CIS Controls v8.1: 17.2 (Establish and maintain contact information), 17.4 (Establish and maintain incident response process)
Riksdagsmonitor implements a risk-based vulnerability management program with defined Service Level Agreements (SLAs) for remediation.
graph LR
Detect[๐ Detect<br/>Scanner finds vulnerability] --> Triage{๐ฏ Triage<br/>Assess severity<br/>& exploitability}
Triage -->|Critical| C[๐ด Critical<br/>24h SLA]
Triage -->|High| H[๐ High<br/>7d SLA]
Triage -->|Medium| M[๐ก Medium<br/>30d SLA]
Triage -->|Low| L[๐ข Low<br/>90d SLA]
C --> Remediate[๐ง Remediate<br/>Apply patch/fix]
H --> Remediate
M --> Remediate
L --> Remediate
Remediate --> Verify[โ
Verify<br/>Re-scan & test]
Verify --> Pass{Verification<br/>Passed?}
Pass -->|Yes| Close[โ๏ธ Close<br/>Document fix]
Pass -->|No| Remediate
Close --> Monitor[๐๏ธ Monitor<br/>Continuous scanning]
Monitor --> Detect
style Detect fill:#4dabf7,color:#000000
style C fill:#ff0000,color:#fff
style H fill:#ff6b6b,color:#000000
style M fill:#ffd43b,color:#000000
style L fill:#51cf66,color:#000000
style Remediate fill:#da77f2,color:#000000
style Verify fill:#20c997,color:#000000
style Close fill:#e9ecef,color:#000000
| Severity | CVSS Score | Response SLA | Fix SLA | Verification SLA | Total SLA |
|---|---|---|---|---|---|
| Critical | 9.0-10.0 | 4 hours | 20 hours | 4 hours | 24 hours |
| High | 7.0-8.9 | 24 hours | 5 days | 1 day | 7 days |
| Medium | 4.0-6.9 | 7 days | 21 days | 2 days | 30 days |
| Low | 0.1-3.9 | 30 days | 58 days | 2 days | 90 days |
SLA Start: Clock starts when vulnerability is first detected by automated scanner or manually reported
SLA Pause Conditions:
Factors Considered:
Severity Adjustment Examples:
| Scanner | Type | Coverage | Frequency | Status |
|---|---|---|---|---|
| Dependabot | SCA (Software Composition Analysis) | npm packages, GitHub Actions | Daily | โ Active |
| CodeQL | SAST (Static Application Security Testing) | JavaScript, HTML | Every PR + weekly | โ Active |
| GitHub Secret Scanning | Credential scanning | Git history, new commits | Every push | โ Active |
| npm audit | SCA | npm packages | Every CI run | โ Active |
| Manual Code Review | Human review | All code changes | Every PR | โ Active |
| Strategy | Use Case | Pros | Cons | Preference |
|---|---|---|---|---|
| Update Dependency | Patch available | Fast, low risk | May introduce breaking changes | โญโญโญโญโญ Preferred |
| Pin Older Version | Patch not available, regression risk | Stable, fast | Accumulates technical debt | โญโญ Last resort |
| Refactor Code | Architectural issue | Eliminates root cause | Time-consuming | โญโญโญโญ Long-term fix |
| Workaround | Blocking issue, patch unavailable | Unblocks development | Technical debt | โญโญโญ Temporary |
| Accept Risk | False positive, minimal impact | No work required | Requires CISO approval | โญ Exception only |
Automated Patching (Dependabot):
Manual Patching:
security/CVE-YYYY-NNNNNZero-Day Response:
Key Performance Indicators (KPIs):
Monthly Security Report:
ISO 27001: A.12.6 (Technical vulnerability management), A.14.2 (Security in development)
NIST CSF 2.0: PR.IP-12 (Vulnerability management plan), DE.CM-8 (Vulnerability scans performed)
CIS Controls v8.1: 7.1 (Establish a vulnerability management process), 7.2 (Establish a remediation process)
Riksdagsmonitor leverages extensive automation to reduce manual security overhead and accelerate response times.
| Automation | Tool | Trigger | Actions | Benefit |
|---|---|---|---|---|
| Dependency Updates | Dependabot | Daily scan | Create PRs for patches | 90% reduction in manual updates |
| Vulnerability Scanning | CodeQL | Every PR | SAST analysis, block merge if findings | 100% code coverage |
| Secret Detection | GitHub Secret Scanning | Every push | Block push, alert security team | Prevents credential leaks |
| Build Provenance | GitHub Attestations | Every release | Generate SLSA attestations | Supply chain verification |
| SBOM Generation | Anchore | Every release | Generate SPDX SBOM | License compliance, vulnerability tracking |
| Workflow Hardening | step-security/harden-runner | Every workflow | Monitor syscalls, network egress | Detect supply chain attacks |
| Branch Protection | GitHub | Every push to main | Require reviews, status checks | Prevent unauthorized changes |
Dependabot is configured to automatically monitor and update both npm dependencies and GitHub Actions workflows, with daily checks for new versions and security patches. Minor and patch npm updates are grouped for reduced noise.
The authoritative configuration is maintained in .github/dependabot.yml. Refer to that file for the exact ecosystems, schedules, labels, groups, and other settings currently in effect.
Auto-Merge Policy:
File: .github/workflows/codeql.yml
Query Suites:
Scan Frequency:
0 0 * * 1)False Positive Management:
File: .github/workflows/release.yml (Build job)
- name: Generate SLSA Build Provenance
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
with:
subject-path: 'riksdagsmonitor-*.zip'
Attestation Contents:
Purpose: Monitor GitHub Actions workflow execution for supply chain attacks
Capabilities:
Configuration (every workflow):
- name: Harden Runner
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
with:
egress-policy: audit # Log all network egress (block mode planned 2027 Q2)
allowed-endpoints: >
github.com:443
api.github.com:443
raw.githubusercontent.com:443
registry.npmjs.org:443
data.imf.org:443
api.imf.org:443
www.imf.org:443
| Metric | Current | Target | Status |
|---|---|---|---|
| Automated Vulnerability Detection | 100% | 100% | โ Met |
| Dependabot PR Merge Rate | 85% | 90% | ๐ก Improving |
| CodeQL False Positive Rate | 8% | <10% | โ Met |
| Mean Time to Deploy Security Patch | 2.5 hours | <4 hours | โ Met |
| Manual Security Tasks | 2 hours/week | <1 hour/week | ๐ก Improving |
ROI of Automation:
ISO 27001: A.14.2 (Security in development and support), A.12.1 (Operational procedures)
NIST CSF 2.0: PR.IP-1 (Configuration baseline established), PR.IP-12 (Vulnerability management)
CIS Controls v8.1: 16.1 (Secure application development), 16.9 (Separate production and non-production environments)
Riksdagsmonitor maintains operational resilience through comprehensive business continuity planning, disaster recovery testing, and operational runbooks.
| Objective | Target | Actual | Status |
|---|---|---|---|
| RTO (Recovery Time Objective) | <15 minutes | <5 minutes (DNS failover) | โ Exceeds target |
| RPO (Recovery Point Objective) | <15 minutes | <15 minutes (S3 replication) | โ Meets target |
| MTTR (Mean Time to Repair) | <2 hours | 1.2 hours (average) | โ Exceeds target |
| Availability SLA | 99.9% | 99.95% (measured) | โ Exceeds target |
Scope: Ensure continuity of Riksdagsmonitor service during disruptions (technical failures, security incidents, natural disasters)
Critical Business Functions:
BCP Scenarios:
| Scenario | Likelihood | Impact | Response Strategy | RTO | Status |
|---|---|---|---|---|---|
| AWS Region Outage | Low (1/year) | High | Automatic DNS failover to GitHub Pages | <5 min | โ Tested |
| GitHub Platform Outage | Low (1/year) | Medium | AWS primary continues serving traffic | 0 min | โ Tested |
| DDoS Attack | Medium (4/year) | Medium | AWS Shield + CloudFront absorption | <1 min | โ Active |
| Security Breach | Low (1/year) | High | Incident response plan (ยง2.7) | <1 hour | โ Ready |
| Key Personnel Unavailable | Medium | Low | Documentation + on-call rotation | <24 hours | โ Ready |
| Credential Compromise | Low | High | Revoke + rotate + audit | <4 hours | โ Ready |
BCP Testing Schedule:
For complete BCP documentation, see BCPPlan.md.
Last DR Test Results (2026-02-15):
Next DR Test (2026-05-15):
| Runbook | Purpose | Location | Last Updated |
|---|---|---|---|
| Deployment Runbook | Deploy new releases | RELEASE_PROCESS.md | 2026-02-18 |
| Incident Response Runbook | Respond to security incidents | ยง2.7 + THREAT_MODEL.md | 2026-02-20 |
| DR Failover Runbook | Fail over to GitHub Pages | Embedded in Route 53 health checks | 2026-02-10 |
| Vulnerability Response Runbook | Remediate vulnerabilities | ยงVulnerability Management | 2026-02-20 |
| Rollback Runbook | Revert bad deployments | WORKFLOWS.md | 2026-02-18 |
On-Call Rotation: Not applicable (solo maintainer, automated monitoring)
Escalation Path:
Contact Information:
Service Level Indicators (SLIs):
Operational Performance (Last 90 Days):
ISO 27001: A.17.1 (Information security continuity), A.17.2 (Redundancies)
NIST CSF 2.0: RC.RP-1 (Recovery plan executed), RC.CO-3 (Recovery activities communicated)
CIS Controls v8.1: 11.1 (Data recovery capability), 11.3 (Protect recovery data)
Riksdagsmonitor implements Infrastructure as Code (IaC) principles using GitHub Actions workflows and enforces configuration compliance through automated policies.
Philosophy: All infrastructure configuration managed through version-controlled code (GitHub Actions workflows, CloudFormation templates).
| Component | IaC Tool | Source | Drift Detection | Status |
|---|---|---|---|---|
| GitHub Actions Workflows | YAML | .github/workflows/*.yml | Git version control | โ Managed |
| AWS S3 Buckets | AWS CLI (scripted) | .github/workflows/deploy-aws.yml | Manual audit | ๐ก Scripted |
| AWS CloudFront | AWS Console (manual) | N/A | Manual audit | ๐ด Manual |
| AWS Route 53 | AWS Console (manual) | N/A | Manual audit | ๐ด Manual |
| Branch Protection Rules | GitHub UI | Documented in CONTRIBUTING.md | Manual audit | ๐ก Documented |
| Dependabot Configuration | YAML | .github/dependabot.yml | Git version control | โ Managed |
Roadmap (2027 Q2): Migrate AWS CloudFront + Route 53 to Terraform for full IaC management.
Applied to: main branch
| Rule | Configuration | Purpose | Status |
|---|---|---|---|
| Require Pull Request | 1 approving review | Prevent direct pushes | โ Enforced |
| Require Status Checks | CodeQL, tests, build | Ensure quality gates pass | โ Enforced |
| Require Signed Commits | GPG signing mandatory | Verify commit authenticity | โ Enforced |
| Dismiss Stale Reviews | On new commits | Require re-review after changes | โ Enforced |
| Restrict Pushes | Admins only bypass | Prevent accidental force pushes | โ Enforced |
| Require Linear History | No merge commits | Maintain clean git history | โ Enforced |
Audit Frequency: Quarterly review of branch protection rules (next: 2026-05-01)
Manual Audit Process (Quarterly):
Last Configuration Audit: 2026-02-10 (No drift detected)
Next Configuration Audit: 2026-05-10
Automated Drift Detection (Planned 2027 Q2):
Continuous Compliance Checks:
| Compliance Requirement | Verification Method | Frequency | Status |
|---|---|---|---|
| MFA Enforced | GitHub organization audit | Real-time | โ Automated |
| GPG Signing Required | GitHub branch protection | Real-time (per commit) | โ Automated |
| Dependency Vulnerabilities | Dependabot | Daily | โ Automated |
| Code Vulnerabilities | CodeQL | Every PR + weekly | โ Automated |
| TLS 1.3 Enforced | CloudFront configuration | Quarterly audit | ๐ก Manual |
| HSTS Headers | HTTP response headers check | Quarterly audit | ๐ก Manual |
| Access Control Review | GitHub audit log review | Quarterly | ๐ก Manual |
Compliance Dashboard: GitHub Security tab provides real-time compliance status for Dependabot, CodeQL, and Secret Scanning.
Change Types:
| Change Type | Approval Required | Testing Required | Rollback Plan | Examples |
|---|---|---|---|---|
| Standard | 1 reviewer | Unit + E2E tests | Git revert | Bug fixes, content updates |
| Significant | 2 reviewers | Full test suite + manual QA | Git revert + re-deploy | Feature additions, dependency major upgrades |
| Emergency | CISO post-approval | Basic smoke tests only | Git revert + hotfix | Critical security patches, service outages |
Emergency Change Process:
Change Advisory Board (CAB): Not applicable (solo maintainer). For multi-maintainer projects, CAB would meet monthly to review significant changes.
ISO 27001: A.8.32 (Change management), A.12.1 (Operational procedures)
NIST CSF 2.0: PR.IP-1 (Configuration baseline), PR.IP-3 (Change control processes)
CIS Controls v8.1: 4.1 (Configuration baseline), 4.2 (Secure configuration implementation)
Riksdagsmonitor implements comprehensive monitoring across infrastructure, application, and security dimensions.
Metrics Dashboard:
| Metric | Threshold | Alert Action | Purpose |
|---|---|---|---|
| CloudFront 5xx Error Rate | >5% for 5 min | PagerDuty alert | Detect origin failures |
| CloudFront Cache Hit Ratio | <80% for 10 min | Email alert | Identify cache inefficiency |
| S3 Replication Lag | >30 minutes | Email alert | Ensure DR readiness |
| Route 53 Health Check | 3 consecutive failures | Automatic DNS failover | Failover to GitHub Pages |
| S3 Bucket Size | >10 GB | Email alert (informational) | Monitor storage growth |
Log Retention:
riksdagsmonitor-logs-cloudfront)riksdagsmonitor-logs-s3)riksdagsmonitor-logs-cloudtrail)Log Analysis:
Audit Scope:
Audit Retention: 90 days (GitHub Free), 180 days (GitHub Enterprise - if upgraded)
Audit Review Process:
Key Security Metrics (Updated Monthly):
| Metric | Current | Target | Trend | Status |
|---|---|---|---|---|
| Open Vulnerabilities | 3 | <5 | โ Decreasing | โ Good |
| Mean Time to Remediate (MTTR) | 2.5 days | <7 days | โ Improving | โ Good |
| Dependabot PR Merge Rate | 85% | >90% | โ Increasing | ๐ก Improving |
| CodeQL False Positive Rate | 8% | <10% | โ Stable | โ Good |
| Security Incidents | 0 (last 90 days) | 0 | โ Stable | โ Good |
| Availability (SLA) | 99.98% | >99.9% | โ Exceeding | โ Excellent |
Security Score (OpenSSF Scorecard): ~8.2/10 (estimated; run gh api repos/Hack23/riksdagsmonitor/properties/values or OpenSSF Scorecard CLI for current value)
User Experience Metrics (Real User Monitoring via CloudFront):
| Metric | p50 | p95 | p99 | Target | Status |
|---|---|---|---|---|---|
| Time to First Byte (TTFB) | 45ms | 120ms | 280ms | <200ms (p95) | โ Met |
| Page Load Time | 850ms | 1.8s | 3.2s | <2s (p95) | โ Met |
| Cache Hit Ratio | 92% | N/A | N/A | >85% | โ Met |
| Data Transfer (monthly) | 12 GB | N/A | N/A | <100 GB (free tier) | โ Met |
Synthetic Monitoring (Planned 2027 Q2):
AWS Monthly Costs (Projected):
Cost Optimization:
Website Analytics: Not implemented (privacy-first approach, no user tracking)
Traffic Insights (CloudFront Access Logs):
ISO 27001: A.12.4 (Logging and monitoring)
NIST CSF 2.0: DE.CM-1 (Network monitored), DE.CM-7 (Monitoring for unauthorized activity)
CIS Controls v8.1: 8.2 (Collect audit logs), 8.5 (Collect detailed audit logs)
Riksdagsmonitor implements structured security operations with defined procedures, responsibilities, and continuous improvement processes.
Operational Model: Single-person SOC (CISO), augmented with automated monitoring and alerting
Operating Hours:
On-Call Coverage: Not applicable (solo maintainer, automated incident detection)
graph TB
Monitor[๐ Continuous Monitoring<br/>Dependabot, CodeQL, CloudWatch]
Monitor --> Detect{๐ Security Event<br/>Detected?}
Detect -->|No| Monitor
Detect -->|Yes| Alert[๐จ Generate Alert<br/>Email/PagerDuty]
Alert --> Classify{๐ฏ Classify Severity<br/>Critical/High/Medium/Low}
Classify -->|Critical| Immediate[๐ด Immediate Response<br/>CISO notified<br/>24h SLA]
Classify -->|High| Urgent[๐ Urgent Response<br/>Email alert<br/>7d SLA]
Classify -->|Medium| Standard[๐ก Standard Response<br/>Email digest<br/>30d SLA]
Classify -->|Low| Routine[๐ข Routine Response<br/>Monthly review<br/>90d SLA]
Immediate --> Investigate[๐ฌ Investigate<br/>Root cause analysis]
Urgent --> Investigate
Standard --> Investigate
Routine --> Investigate
Investigate --> Respond[๐ก๏ธ Respond<br/>Contain, remediate, verify]
Respond --> Document[๐ Document<br/>Update THREAT_MODEL.md]
Document --> Review[๐ Post-Incident Review<br/>Lessons learned]
Review --> Improve[โก Improve<br/>Update procedures/controls]
Improve --> Monitor
style Monitor fill:#4dabf7,color:#000000
style Alert fill:#ff6b6b,color:#000000
style Immediate fill:#ff0000,color:#fff
style Urgent fill:#ff6b6b,color:#000000
style Standard fill:#ffd43b,color:#000000
style Routine fill:#51cf66,color:#000000
style Investigate fill:#da77f2,color:#000000
style Respond fill:#20c997,color:#000000
style Document fill:#868e96,color:#000000
style Review fill:#e9ecef,color:#000000
style Improve fill:#51cf66,color:#000000
| Procedure | Frequency | Responsible | Last Executed | Next Scheduled |
|---|---|---|---|---|
| Vulnerability Scanning | Daily (automated) | Dependabot | 2026-02-20 | 2026-02-21 |
| Code Scanning | Every PR + weekly | CodeQL | 2026-02-19 | 2026-02-26 |
| Security Alert Triage | Daily | CISO | 2026-02-20 | 2026-02-21 |
| Access Control Review | Quarterly | CISO | 2026-02-01 | 2026-05-01 |
| Configuration Audit | Quarterly | CISO | 2026-02-10 | 2026-05-10 |
| DR Failover Test | Quarterly | CISO | 2026-02-15 | 2026-05-15 |
| Incident Response Drill | Annually | CISO | 2025-08-15 | 2026-08-15 |
| Security Architecture Review | Annually | CISO + CEO | 2026-02-20 | 2027-02-20 |
Daily:
Weekly:
Monthly:
Quarterly:
Annually:
Lessons Learned (After Every Incident):
Security Metrics Review (Monthly):
Threat Landscape Monitoring (Quarterly):
ISO 27001: A.16.1 (Incident management), A.12.1 (Operational procedures)
NIST CSF 2.0: DE.AE-5 (Incident alert thresholds), RS.AN-5 (Processes established for receiving, analyzing, and responding)
CIS Controls v8.1: 17.1 (Designate incident handling personnel), 17.9 (Establish incident scoring and prioritization schema)
Riksdagsmonitor achieves robust security posture with minimal financial investment by leveraging zero-cost security controls and cloud platform free tiers.
| Category | Tool/Service | Monthly Cost | Annual Cost | Notes |
|---|---|---|---|---|
| Code Scanning | CodeQL (GitHub native) | $0 | $0 | Free for public repos |
| Dependency Scanning | Dependabot (GitHub native) | $0 | $0 | Free for public repos |
| Secret Scanning | GitHub Secret Scanning | $0 | $0 | Free for public repos |
| CI/CD | GitHub Actions | $0 | $0 | Free tier: 2000 min/month (sufficient) |
| Primary Hosting | AWS CloudFront + S3 | $10-15 | $120-180 | Mostly within free tier |
| DR Hosting | GitHub Pages | $0 | $0 | Free for public repos |
| DNS | AWS Route 53 | $0.50 | $6 | 1 hosted zone |
| DDoS Protection | AWS Shield Standard | $0 | $0 | Included with CloudFront |
| Monitoring | AWS CloudWatch | $0 | $0 | Free tier: 10 metrics, 1 million API requests |
| Audit Logging | AWS CloudTrail | $0 | $0 | Free tier: 1 trail |
| SLSA Attestations | GitHub Attestations | $0 | $0 | Native GitHub feature |
| SBOM Generation | Anchore SBOM Action | $0 | $0 | Open source |
| Workflow Hardening | step-security/harden-runner | $0 | $0 | Free tier |
| Total | $10-15 | $126-186 | Minimal investment |
GitHub Native Security Features (All Free):
.github/workflows/zap-scan.yml (rules baseline .zap/rules.tsv); artifacts retained 90 days. Maps to ISO 27001 A.8.29 / NIST CSF DE.CM-08 / CIS Control 18.AWS Free Tier Security Features:
Manual Effort Avoided (Per Year):
Risk Reduction:
Total Annual ROI: >$16,925 labor savings + risk avoidance for only $126-186/year investment = >9000% ROI
| Investment | Purpose | Estimated Cost | Timeline | ROI |
|---|---|---|---|---|
| AWS WAF | Rate limiting, advanced application protection | $5-10/month | 2027 Q2 | Prevent scraping, abuse |
| Terraform | Full IaC for AWS infrastructure | $0 (tool free) | 2027 Q2 | Reduce config drift, improve repeatability |
| Synthetic Monitoring | External uptime checks (Uptime Robot) | $0 (free tier) | 2027 Q2 | Faster outage detection |
| GitHub Enterprise | Advanced audit logging (180-day retention) | $21/user/month | 2028 | Extended compliance visibility |
Total Planned Investment: $60-120/year additional (2027+)
ISO 27001: A.5.23 (Information security for use of cloud services)
NIST CSF 2.0: ID.BE-3 (Priorities for organizational mission, objectives, and activities are established)
CIS Controls v8.1: N/A (Cost optimization is not directly mapped to security controls)
Riksdagsmonitor demonstrates that robust security is achievable for static websites through defense-in-depth architecture, comprehensive automation, and zero-cost security controls.
โ Strong Security Controls:
โ Compliance Excellence:
โ Operational Efficiency:
9000% ROI on security investment
โ Continuous Improvement:
Current Maturity: Level 4 - Managed and Measurable (out of 5)
Maturity Assessment:
2027 Q2:
2027 Q4:
2028:
npm run preview (current scope: weekly + on-demand against production โ see .github/workflows/zap-scan.yml)Hack23 AB is committed to maintaining the highest security standards for Riksdagsmonitor as a public service for Swedish democratic transparency. Security is not a checkbox but a continuous journey of improvement, adaptation, and vigilance.
Security Contact: security@hack23.com
Responsible Disclosure: See SECURITY.md for vulnerability reporting procedures.
Riksdagsmonitor operates as a civic technology platform providing parliamentary transparency services. As a non-commercial platform operated by a micro-enterprise (Hack23 AB, single employee), Riksdagsmonitor falls under the general applicability provisions of NIS2 but is likely below the threshold for mandatory compliance as a "medium enterprise" (50+ employees or โฌ10M+ turnover required for essential/important entity designation).
However, Hack23 AB voluntarily maps to NIS2 requirements as a best practice and client readiness demonstration.
| NIS2 Article | Requirement | Implementation | Evidence | Status |
|---|---|---|---|---|
| Art. 20 | Governance - Management bodies must approve and oversee cybersecurity measures and take cybersecurity training | CEO (James P. Sรถrling) personally approves all security architecture. Annual ISMS review. CISSP-equivalent knowledge maintained | SECURITY_ARCHITECTURE.md CEO sign-off, annual review record | COMPLIANT |
| Art. 21(1) | Appropriate technical and organizational measures based on risk assessment | Risk-based approach documented in THREAT_MODEL.md. Defense-in-depth with 6 layers. STRIDE analysis. Regular risk reviews | THREAT_MODEL.md, SECURITY_ARCHITECTURE.md, Risk Register (ISMS-PUBLIC) | COMPLIANT |
| Art. 21(2)(a) | Risk analysis and information system security policies | Information Security Policy (ISMS-PUBLIC). SECURITY_ARCHITECTURE.md as operational security policy. Annual review cycle | Information_Security_Policy.md, SECURITY_ARCHITECTURE.md v2.1 | COMPLIANT |
| Art. 21(2)(b) | Incident handling including detection, response, and notification | BCPPlan.md with 3 IR playbooks. ISMS Incident Response Plan. GitHub Security Advisories. Alert monitoring | BCPPlan.md IR Playbooks IR-PB-001/002/003, ISMS IRP | COMPLIANT |
| Art. 21(2)(c) | Business continuity including backup management, disaster recovery, crisis management | Dual-deployment (CloudFront + GitHub Pages). S3 multi-region replication. RTO <30s (origin), <15min (DNS). BCPPlan.md | BCPPlan.md, AWS multi-region S3 config, Route 53 health checks | COMPLIANT |
| Art. 21(2)(d) | Supply chain security including third-party services | Dependabot monitors all npm dependencies. GitHub Actions third-party action pinning. step-security/harden-runner. Third Party Management Policy (ISMS-PUBLIC) | Third_Party_Management.md, Dependabot config, pinned action SHAs | COMPLIANT |
| Art. 21(2)(e) | Security in network and information systems acquisition, development and maintenance | Secure development policy (ISMS-PUBLIC). CodeQL SAST in every PR. SLSA provenance. Dependency review gates | Secure_Development_Policy.md, GitHub Actions YAML, SLSA attestation | COMPLIANT |
| Art. 21(2)(f) | Policies and procedures to assess effectiveness of measures | OpenSSF Scorecard monthly monitoring (8.2/10). Security metrics tracked (MTTP, scan pass rates). Annual security architecture review | OpenSSF Scorecard badge, Security_Metrics.md (ISMS-PUBLIC), Git commit history | COMPLIANT |
| Art. 21(2)(g) | Basic cyber hygiene practices and cybersecurity training | CEO maintains up-to-date security knowledge. ISMS documentation current. All ISMS policies reviewed annually. GitHub security advisories reviewed weekly | Policy review dates in ISMS, security training evidence | COMPLIANT |
| Art. 21(2)(h) | Cryptography policies including encryption | Cryptography Policy (ISMS-PUBLIC). TLS 1.3 enforced. HSTS preloaded. SHA-256 for integrity. Sigstore for signing. No weak ciphers | Cryptography_Policy.md, CloudFront TLS configuration, HSTS header | COMPLIANT |
| Art. 21(2)(i) | Human resources security, access control, and asset management | Single-person company. All access controlled via GitHub and AWS IAM. Asset Register maintained (ISMS-PUBLIC). Access Control Policy | Access_Control_Policy.md, Asset_Register.md, GitHub access controls | COMPLIANT |
| Art. 21(2)(j) | Multi-factor authentication or continuous authentication solutions | GitHub account secured with MFA. AWS root account secured with hardware MFA. GitHub repository requires authenticated writes. SSH key required for Git operations | GitHub MFA enforcement settings, AWS MFA device attachment | COMPLIANT |
| Art. 23 | Significant incident reporting to competent authority within 24h (initial) / 72h (full) | Incident Response Plan includes NIS2 assessment step. BCPPlan.md IR playbooks include NIS2 notification requirement. Competent authority: Swedish NCSC (NCSC.SE) | BCPPlan.md Section on NIS2 assessment, ISMS IRP notification procedure | COMPLIANT โ procedure documented |
| Art. 25 | Standardization โ use of European and international standards | ISO 27001:2022, NIST CSF 2.0, CIS Controls v8.1 alignment. EU CRA conformity. SLSA supply chain standards | SECURITY_ARCHITECTURE.md framework mappings, CRA-ASSESSMENT.md | COMPLIANT |
| Art. 32 | Supervisory measures for essential entities | Not applicable โ Hack23 AB below essential entity threshold. Voluntary compliance demonstrated | Entity size assessment (micro-enterprise) | NOT APPLICABLE โ voluntary |
| Art. 33 | Supervisory measures for important entities | Not applicable โ Hack23 AB below important entity threshold | Entity size assessment (micro-enterprise) | NOT APPLICABLE โ voluntary |
This section maps all 10 OWASP Top 10 for Large Language Model Applications risks to the Riksdagsmonitor MCP content generation pipeline.
| OWASP LLM Risk | Risk Description | Riksdagsmonitor Mitigation | Implementation | Risk Level |
|---|---|---|---|---|
| LLM01: Prompt Injection | Malicious content in retrieved data manipulates LLM behavior | riksdag-regering-mcp fetches only structured JSON from authenticated riksdag.se API. MCP tool outputs are data objects, not raw text. Prompt template is version-controlled and reviewed. User input never included in prompts | Structured data pipeline, no free-text user input, prompt templates in Git | LOW |
| LLM02: Insecure Output Handling | LLM output injected into downstream systems without sanitization | All LLM-generated HTML is validated by HTMLHint before merge. Content Security Policy headers prevent XSS execution. Output encoding applied. Human reviewer inspects content before publication | HTMLHint validation, CSP headers, human review gate, PR review required | MEDIUM โ human review mitigates |
| LLM03: Training Data Poisoning | Manipulated training data causes malicious model behavior | Riksdagsmonitor uses GitHub Copilot-hosted Claude Sonnet 4.6 models (not self-trained). Anthropic provides model-level safety measures. Model selection from trusted provider | GitHub Copilot engine, Anthropic safety training, no fine-tuning on riksdag data | LOW |
| LLM04: Model Denial of Service | Excessive resource consumption through crafted inputs | GitHub Actions MCP jobs have timeout limits. Tool calls are time-bounded. Max 3 retries with exponential backoff. Daily cron (not continuous). Input data size limits in MCP tools | GitHub Actions timeout configuration, retry limits, cron scheduling | LOW |
| LLM05: Supply Chain Vulnerabilities | Compromised components in LLM application stack | npm packages SHA-pinned via package-lock.json. GitHub Actions pinned to commit SHAs. Dependabot monitors all dependencies. step-security/harden-runner blocks unauthorized egress. SLSA provenance attestation | package-lock.json, SHA-pinned Actions, Dependabot, SLSA attestation | MEDIUM |
| LLM06: Sensitive Information Disclosure | LLM reveals confidential data in outputs | Zero PII in data sources (all Riksdag data is public political information). No sensitive data in prompts. No user data processed. Data classification: all data PUBLIC | Data classification policy, no-PII architecture, source data is public | LOW |
| LLM07: Insecure Plugin Design | Unsafe LLM plugin/tool implementations | MCP server (riksdag-regering-mcp) has defined tool schema with typed parameters. No arbitrary code execution. Read-only API access. All MCP tool outputs are structured JSON | MCP tool schema definitions, read-only API access, structured outputs | LOW |
| LLM08: Excessive Agency | LLM performs unintended actions with excessive permissions | Agent phase uses read-only repository and MCP access. Write actions are isolated to the safe-output PR boundary. No direct merge or deployment permission is granted to the LLM pipeline. All outputs require human approval (PR review) before publication | Least privilege, read-only MCP access, safe-output boundary, human review gate, PR-required merge | LOW |
| LLM09: Overreliance | Excessive trust in LLM outputs without human verification | Mandatory human review (PR review by James P. Sรถrling) before any generated article is published. Quality score threshold (0.8/1.0) gates generation. Correction policy for published errors. Human retains final editorial control | PR review requirement, quality gate, editorial policy, correction procedure | LOW |
| LLM10: Model Theft | Unauthorized extraction or replication of model | Model access is mediated by GitHub Copilot / GitHub Actions runtime controls. No model weights are available to workflows. Tokens are masked in logs and scoped by job. step-security/harden-runner monitors egress | GitHub token scoping, secrets masking, no model weights, egress monitoring | LOW |
Overall LLM Risk Assessment for Riksdagsmonitor MCP Pipeline: LOW-MEDIUM
The primary residual risks are LLM02 (output handling) mitigated by human review, and LLM05 (supply chain) mitigated by dependency pinning. The architecture's read-only data access, public data sources only, and mandatory human review gate collectively create a strong defense-in-depth posture.
Statement of Applicability (SoA) for Riksdagsmonitor - ISO 27001:2022 Annex A Controls
Scope: Riksdagsmonitor platform, all associated GitHub repositories, AWS infrastructure, and CI/CD pipelines.
Note: Riksdagsmonitor is not yet formally ISO 27001 certified. This SoA documents alignment as preparation for future certification.
| Control ID | Control Name | Applicable | Justification | Implementation Status |
|---|---|---|---|---|
| 5.1 | Policies for information security | Y | Governance requirement | ISMS-PUBLIC Information Security Policy |
| 5.2 | Information security roles and responsibilities | Y | Operational requirement | CEO/CISO: James P. Sรถrling |
| 5.3 | Segregation of duties | N | Single-person micro-enterprise โ compensating controls: automated tooling, documented procedures | N/A โ compensating controls documented |
| 5.4 | Management responsibilities | Y | Governance requirement | CEO accountable for ISMS |
| 5.5 | Contact with authorities | Y | Incident response requirement | NCSC.SE, security@hack23.com |
| 5.6 | Contact with special interest groups | Y | Threat intelligence | GitHub Security Advisories, CISA |
| 5.7 | Threat intelligence | Y | Risk management | THREAT_MODEL.md, Dependabot, CVE feeds |
| 5.8 | Information security in project management | Y | Development lifecycle | Secure development policy, threat modeling |
| 5.9 | Inventory of information and other assets | Y | Asset management | Asset Register (ISMS-PUBLIC) |
| 5.10 | Acceptable use of information and assets | Y | Governance | Acceptable use defined in ISMS policies |
| 5.11 | Return of assets | N | No employees beyond CEO | N/A โ single person |
| 5.12 | Classification of information | Y | Data protection | Data Classification Policy (ISMS-PUBLIC) |
| 5.13 | Labelling of information | Y | Data handling | Classification badges on all docs |
| 5.14 | Information transfer | Y | Data protection | TLS 1.3 for all transfers, no sensitive transfers |
| 5.15 | Access control | Y | Security requirement | GitHub access controls, AWS IAM |
| 5.16 | Identity management | Y | Access control | GitHub identity, AWS IAM users |
| 5.17 | Authentication information | Y | Access control | MFA on GitHub, SSH keys for Git |
| 5.18 | Access rights | Y | Least privilege | Branch protection, workflow permissions |
| 5.19 | Information security in supplier relationships | Y | Third-party risk | Third Party Management Policy (ISMS-PUBLIC) |
| 5.20 | Addressing information security in supplier agreements | Y | Third-party contracts | GitHub ToS, AWS ToS, Anthropic ToS reviewed |
| 5.21 | Managing information security in the ICT supply chain | Y | Supply chain security | Dependabot, SHA pinning, SLSA |
| 5.22 | Monitoring, review and change management of supplier services | Y | Third-party monitoring | Dependabot alerts, GitHub status, AWS status |
| 5.23 | Information security for use of cloud services | Y | Cloud governance | AWS CloudFront/S3, GitHub Pages policies |
| 5.24 | Information security incident management planning | Y | Incident response | BCPPlan.md, ISMS IRP, IR Playbooks |
| 5.25 | Assessment and decision on information security events | Y | Incident triage | Severity classification in IR playbooks |
| 5.26 | Response to information security incidents | Y | Incident response | IR-PB-001, IR-PB-002, IR-PB-003 playbooks |
| 5.27 | Learning from information security incidents | Y | Continual improvement | Post-incident review in all playbooks |
| 5.28 | Collection of evidence | Y | Forensics | Evidence collection checklists in playbooks |
| 5.29 | Information security during disruption | Y | Business continuity | BCPPlan.md dual-deployment architecture |
| 5.30 | ICT readiness for business continuity | Y | Business continuity | RTO/RPO defined, tested quarterly |
| 5.31 | Legal, statutory, regulatory and contractual requirements | Y | Compliance | GDPR, CRA, NIS2 mapping documented |
| 5.32 | Intellectual property rights | Y | Legal compliance | OSS license compliance, data attribution |
| 5.33 | Protection of records | Y | Evidence preservation | Git history retention, audit log retention |
| 5.34 | Privacy and protection of personal data | Y | GDPR compliance | Zero PII architecture, privacy by design |
| 5.35 | Independent review of information security | Y | Audit | OpenSSF Scorecard, GitHub security features |
| 5.36 | Compliance with policies, rules, and standards | Y | Governance | Annual ISMS review, quarterly threat model |
| 5.37 | Documented operating procedures | Y | Operational security | WORKFLOWS.md, BCPPlan.md, runbooks |
| 6.1 | Screening | N | No employees beyond CEO โ not applicable | N/A |
| 6.2 | Terms and conditions of employment | N | No employees beyond CEO | N/A |
| 6.3 | Information security awareness, education and training | Y | Security awareness | CEO maintains security knowledge |
| 6.4 | Disciplinary process | N | No employees beyond CEO | N/A |
| 6.5 | Responsibilities after termination | N | No employees beyond CEO | N/A |
| 6.6 | Confidentiality or non-disclosure agreements | N | All data is public civic data | N/A |
| 6.7 | Remote working | N | All operations are remote-native by design | N/A โ inherently remote |
| 6.8 | Information security event reporting | Y | Incident management | security@hack23.com, GitHub Security |
| 7.1 | Physical security perimeters | N | No physical office/datacenter โ cloud-only | N/A โ cloud SaaS |
| 7.2 | Physical entry | N | No physical premises | N/A |
| 7.3 | Securing offices, rooms and facilities | N | No physical premises | N/A |
| 7.4 | Physical security monitoring | N | No physical premises | N/A |
| 7.5 | Protecting against physical and environmental threats | N | Managed by GitHub/AWS | N/A โ cloud responsibility |
| 7.6 | Working in secure areas | N | No physical secure areas | N/A |
| 7.7 | Clear desk and clear screen | N | No physical office | N/A |
| 7.8 | Equipment siting and protection | N | No owned equipment in scope | N/A โ cloud-only |
| 7.9 | Security of assets off-premises | Y | Laptop used for development | Full disk encryption, VPN policy |
| 7.10 | Storage media | Y | Development laptop storage | Encrypted disk, no sensitive data on media |
| 7.11 | Supporting utilities | N | Managed by GitHub/AWS | N/A โ cloud responsibility |
| 7.12 | Cabling security | N | No physical infrastructure | N/A |
| 7.13 | Equipment maintenance | N | No owned infrastructure in scope | N/A โ cloud only |
| 7.14 | Secure disposal or re-use of equipment | Y | Development laptop eventual disposal | Secure wipe procedure documented |
| 8.1 | User endpoint devices | Y | Developer laptop security | Encrypted disk, patched OS, screen lock |
| 8.2 | Privileged access rights | Y | GitHub admin, AWS root | MFA required, least privilege IAM |
| 8.3 | Information access restriction | Y | Repository access | Branch protection, no public write |
| 8.4 | Access to source code | Y | Code security | Private secrets in GitHub Secrets, not code |
| 8.5 | Secure authentication | Y | MFA for all admin access | GitHub MFA, AWS hardware MFA |
| 8.6 | Capacity management | Y | Performance | CloudFront CDN elastic capacity |
| 8.7 | Protection against malware | Y | Endpoint and pipeline | Dependabot, CodeQL, npm audit |
| 8.8 | Management of technical vulnerabilities | Y | Vulnerability management | Dependabot, MTTP targets, patch policy |
| 8.9 | Configuration management | Y | Secure configuration | IaC (planned), documented configs, branch protection |
| 8.10 | Information deletion | Y | Data lifecycle | Content archival policy, no PII to delete |
| 8.11 | Data masking | N | No PII processed | N/A โ no sensitive data |
| 8.12 | Data leakage prevention | Y | DLP for source code | GitHub secret scanning, no secrets in code |
| 8.13 | Information backup | Y | Backup and recovery | Git history as backup, S3 multi-region, GitHub Pages |
| 8.14 | Redundancy of information processing | Y | High availability | Dual-deployment, multi-region S3, CloudFront |
| 8.15 | Logging | Y | Security monitoring | GitHub audit logs, CloudFront logs, Actions logs |
| 8.16 | Monitoring activities | Y | Continuous monitoring | Dependabot, CodeQL, OpenSSF Scorecard |
| 8.17 | Clock synchronization | Y | Log integrity | GitHub/AWS NTP-synchronized timestamps |
| 8.18 | Use of privileged utility programs | N | No privileged utilities in scope | N/A |
| 8.19 | Installation of software on operational systems | Y | Change control | GitHub Actions CI/CD gates, branch protection |
| 8.20 | Networks security | Y | Network controls | HTTPS-only, TLS 1.3, HSTS, CSP headers |
| 8.21 | Security of network services | Y | Service security | CloudFront WAF-ready, DDoS protection |
| 8.22 | Segregation of networks | N | Static site โ no internal network | N/A โ no network to segregate |
| 8.23 | Web filtering | N | No browsing activity in scope | N/A |
| 8.24 | Use of cryptography | Y | Cryptographic controls | TLS 1.3, SHA-256, Sigstore, HSTS |
| 8.25 | Secure development life cycle | Y | SDLC security | CodeQL, Dependabot, threat modeling, SLSA |
| 8.26 | Application security requirements | Y | Security requirements | THREAT_MODEL.md security requirements |
| 8.27 | Secure system architecture and engineering principles | Y | Secure design | Defense-in-depth, least privilege, static-first |
| 8.28 | Secure coding | Y | Coding standards | ESLint, CodeQL, HTMLHint, PR review |
| 8.29 | Security testing in development and acceptance | Y | Security testing | Cypress E2E, Vitest, CodeQL, Dependabot |
| 8.30 | Outsourced development | N | No outsourced development | N/A |
| 8.31 | Separation of development, test and production environments | Y | Environment control | Branch-based dev, separate GitHub Pages deployment |
| 8.32 | Change management | Y | Change control | PR review, branch protection, changelog |
| 8.33 | Test information | Y | Test data | Tests use synthetic/public data only |
| 8.34 | Protection of information systems during audit testing | N | No formal audit testing currently | Planned for ISO certification |
SoA Summary:
NIST CSF 2.0 introduced the new GOVERN (GV) function as the sixth function, providing organizational context for all other functions.
| Subcategory | Description | Riksdagsmonitor Implementation |
|---|---|---|
| GV.OC-01 | The organizational mission is understood and informs cybersecurity risk management | Mission: "Provide free, transparent access to Swedish parliamentary data for democratic accountability." Security enables availability of this civic service. Documented in README.md and SECURITY_ARCHITECTURE.md |
| GV.OC-02 | Internal and external stakeholders are understood and their needs considered | Stakeholders: Swedish public (users), researchers, journalists, Hack23 AB (operator). External: GitHub, AWS, Anthropic (providers), Riksdag (data source). Mapped in THREAT_MODEL.md |
| GV.OC-03 | Legal, regulatory, and contractual cybersecurity obligations are understood and managed | GDPR (no PII), CRA (documented in CRA-ASSESSMENT.md), NIS2 (voluntary alignment), Swedish law compliance. Legal review annually |
| GV.OC-04 | Critical objectives, capabilities, and services that stakeholders depend on are understood and communicated | Critical service: 24/7 web availability of political transparency data. Documented in BCPPlan.md BIA section. RTO/RPO defined |
| GV.OC-05 | Outcomes, capabilities, and services that the organization depends on are understood and communicated | Dependencies: GitHub (source control, CI/CD, Pages, Copilot engine), AWS (CDN, S3), Riksdag API (data), Anthropic (Claude Sonnet 4.6 model). Documented in ARCHITECTURE.md and BCPPlan.md |
| Subcategory | Description | Riksdagsmonitor Implementation |
|---|---|---|
| GV.RM-01 | Risk management objectives are established and agreed to by organizational stakeholders | Risk tolerance: accept LOW risks, treat MEDIUM, eliminate HIGH/CRITICAL. Documented in Risk Register (ISMS-PUBLIC). CEO approval for risk acceptance |
| GV.RM-02 | Risk appetite and risk tolerance statements are established, communicated, and maintained | Risk Appetite Statement: Hack23 AB accepts LOW risks inherent to civic tech publishing. MEDIUM risks require compensating controls within 90 days. HIGH/CRITICAL risks must be treated within 30/7 days respectively |
| GV.RM-03 | Cybersecurity risk management activities and outcomes are included in enterprise risk management | Single-person company โ security risks managed directly by CEO. Risk Register integrated with ISMS. Security metrics reported monthly (self-reporting) |
| GV.RM-04 | Strategic-level cybersecurity risk is documented as organizational risk | Key organizational risks: platform unavailability, reputational risk from data errors, supply chain compromise. Documented in THREAT_MODEL.md and SWOT.md |
| GV.RM-05 | Lines of communication across the organization regarding cybersecurity risks are established | CEO is sole person โ direct ownership. External: security@hack23.com for public disclosure. GitHub Issues for tracking |
| GV.RM-06 | A standardized approach to calculating, documenting, and prioritizing cybersecurity risk is established | STRIDE + DREAD methodology in THREAT_MODEL.md. Risk scoring: Likelihood (1-5) x Impact (1-5). CVSS scores for technical vulnerabilities |
| GV.RM-07 | Strategic opportunities (positive risks) are characterized and included in organizational cybersecurity risk discussions | Opportunities mapped in FUTURE_SWOT.md: EU grants, research partnerships, Nordic expansion. Security as enabler of civic trust and business growth |
| Role | Name | Responsibilities |
|---|---|---|
| CEO/CISO/DPO | James Pether Sรถrling | All security architecture, ISMS ownership, incident response, compliance, risk acceptance |
| GitHub Security | GitHub Platform | Secret scanning, CodeQL, Dependabot, audit logging (automated) |
| AWS Security | AWS Platform | CloudFront DDoS protection, S3 encryption, IAM enforcement (platform) |
| Anthropic Safety | Anthropic | Claude Sonnet 4.6 safety guardrails, model security (provider responsibility) |
| Security Community | Public | Responsible disclosure via security@hack23.com |
| Policy Area | Policy Document | Status | Review Cycle |
|---|---|---|---|
| Information Security | Information_Security_Policy.md | Active | Annual |
| Access Control | Access_Control_Policy.md | Active | Annual |
| Cryptography | Cryptography_Policy.md | Active | Annual |
| Data Classification | Data_Classification_Policy.md | Active | Annual |
| Vulnerability Management | Vulnerability_Management.md | Active | Annual |
| Secure Development | Secure_Development_Policy.md | Active | Annual |
| Incident Response | Incident_Response_Plan.md | Active | Annual |
| Business Continuity | BCPPlan.md | Active | Quarterly |
| Third Party Management | Third_Party_Management.md | Active | Annual |
| Open Source | Open_Source_Policy.md | Active | Annual |
| CRA Conformity | CRA_Conformity_Assessment_Process.md | Active | Annual |
| Oversight Activity | Frequency | Evidence | Owner |
|---|---|---|---|
| Security architecture review | Annual | Git commit history (SECURITY_ARCHITECTURE.md) | CEO |
| Threat model review | Quarterly | Git commit history (THREAT_MODEL.md) | CEO |
| ISMS policy review | Annual | Policy documents with review dates | CEO |
| Risk register update | Quarterly | Risk_Register.md (ISMS-PUBLIC) | CEO |
| OpenSSF Scorecard | Monthly | GitHub badge, score history | Automated |
| Dependabot monitoring | Daily | GitHub Security tab | Automated |
| CodeQL scanning | Per commit | GitHub Actions results | Automated |
| BCP testing | Quarterly | BCPPlan.md test results section | CEO |
| Supplier | Category | Risk Level | Controls | Review Frequency |
|---|---|---|---|---|
| GitHub | Source control, CI/CD, hosting | HIGH (critical path) | GitHub Enterprise ToS, ISMS Third Party Policy, MFA, branch protection | Annual contract review |
| AWS | CDN, S3, Route 53 | HIGH (production hosting) | AWS DPA, CloudFront TLS, IAM least privilege, MFA root | Annual contract review |
| Anthropic (via GitHub Copilot) | AI content generation | MEDIUM | GitHub Copilot runtime controls, least-privilege workflow permissions, content filtering, safe-output PR boundary | Annual review |
| riksdag-regering-mcp | Data pipeline | MEDIUM | Pinned version, Dependabot monitoring, code review | Per release |
| npm ecosystem | JavaScript dependencies | MEDIUM | package-lock.json SHA pinning, Dependabot, npm audit | Daily automated |
| GitHub Actions marketplace | CI/CD automation | MEDIUM | SHA-pinned actions only, step-security/harden-runner, egress control | Per workflow update |
| Riksdag API | Data source | LOW (public data only) | Read-only access, schema validation, no credentials | Quarterly check |
Riksdagsmonitor is classified as an IG1/IG2 organization: micro-enterprise (1 employee), civic tech with moderate risk profile.
| CIS Control | Sub-Controls | IG Level | Implemented | Evidence | Notes |
|---|---|---|---|---|---|
| 1: Inventory of Enterprise Assets | 1.1 Establish asset inventory | IG1 | YES | Asset_Register.md (ISMS-PUBLIC) | GitHub repos, AWS resources, laptop |
| 1.2 Address unauthorized assets | IG1 | YES | Branch protection, no unauthorized pushes | Automated via GitHub | |
| 2: Inventory of Software Assets | 2.1 Establish software inventory | IG1 | YES | package.json, GitHub Actions dependencies | npm dependency graph |
| 2.2 Ensure authorized software | IG1 | YES | Dependabot, code review gates | Only approved packages merged | |
| 2.3 Address unauthorized software | IG2 | YES | step-security/harden-runner egress control | Blocks unauthorized software calls | |
| 3: Data Protection | 3.1 Establish data management process | IG1 | YES | Data_Classification_Policy.md | All data: PUBLIC classification |
| 3.2 Inventory sensitive data | IG1 | YES | Asset Register - no sensitive data | Zero PII architecture | |
| 3.3 Configure data access control | IG1 | YES | GitHub access controls, S3 bucket policies | Authenticated write, public read | |
| 3.10 Encrypt sensitive data in transit | IG1 | YES | TLS 1.3, HSTS, CloudFront HTTPS | TLS minimum 1.2, preferred 1.3 | |
| 3.11 Encrypt sensitive data at rest | IG1 | YES | S3 server-side encryption, GitHub at rest | SSE-S3 on all buckets | |
| 4: Secure Configuration | 4.1 Establish secure configuration process | IG1 | YES | SECURITY_ARCHITECTURE.md, ISMS policies | Documented configurations |
| 4.2 Establish and maintain secure configuration for network infrastructure | IG2 | YES | CloudFront security policy, S3 bucket ACL | HTTPS-only policy enforced | |
| 4.3 Configure automatic session timeouts | IG1 | N/A | No user sessions (static site) | Not applicable | |
| 5: Account Management | 5.1 Establish account management process | IG1 | YES | Access_Control_Policy.md | Single admin account with MFA |
| 5.2 Use unique passwords | IG1 | YES | Password manager, MFA eliminates password reliance | MFA required for all privileged access | |
| 5.3 Disable dormant accounts | IG1 | YES | Only active accounts exist | Single-person company | |
| 5.4 Restrict administrator privileges | IG1 | YES | IAM least privilege, workflow token restrictions | Minimal permissions per job | |
| 6: Access Control Management | 6.1 Establish access control process | IG1 | YES | Access_Control_Policy.md | Documented |
| 6.2 Establish IAM processes | IG1 | YES | AWS IAM, GitHub permission model | Implemented | |
| 6.3 Require MFA for externally-exposed applications | IG1 | YES | GitHub MFA, AWS MFA | Hardware MFA on AWS root | |
| 6.4 Require MFA for remote access | IG1 | YES | All access is remote-native with MFA | Cloud-only architecture | |
| 6.7 Centralize access control | IG2 | YES | GitHub and AWS as identity providers | Centralized via cloud platforms | |
| 6.8 Define and maintain role-based access | IG2 | YES | IAM roles, GitHub repository roles | Least privilege roles defined | |
| 7: Continuous Vulnerability Management | 7.1 Establish vulnerability management process | IG1 | YES | Vulnerability_Management.md (ISMS) | Documented process |
| 7.2 Establish remediation process for risks | IG1 | YES | MTTP targets in ISMS: 7/30/90 days by severity | Tracked in GitHub Security tab | |
| 7.3 Perform automated OS patch management | IG1 | N/A | No OS to manage (cloud-hosted) | Managed by GitHub/AWS | |
| 7.4 Perform automated application patch management | IG1 | YES | Dependabot auto-PRs for npm packages | Daily automated scanning | |
| 7.5 Perform automated vulnerability scans | IG2 | YES | CodeQL on every PR, Dependabot daily | Automated scanning | |
| 7.6 Perform automated vulnerability scans of internal enterprise assets | IG3 | PARTIAL | Manual review for dev laptop | External tool scan planned 2027 | |
| 8: Audit Log Management | 8.1 Establish audit log management process | IG1 | YES | GitHub Audit Log, CloudFront logs, Actions logs | Documented log sources |
| 8.2 Collect audit logs | IG1 | YES | GitHub Audit Log API, CloudFront access logs | Automated collection | |
| 8.3 Ensure adequate audit log storage | IG2 | YES | GitHub retains 90-day audit log, S3 log retention | Configured retention policies | |
| 8.11 Conduct audit log reviews | IG2 | YES | Security alerts reviewed, Dependabot monitored | Weekly review by CEO | |
| 9: Email and Web Browser Protections | 9.1 Ensure use of only fully supported browsers | IG1 | YES | Modern browser requirement documented | Tested on latest Chrome, Firefox, Safari |
| 9.6 Block unnecessary file types | IG2 | N/A | Static site serves only HTML/CSS/JS/JSON/PNG | No file upload functionality | |
| 10: Malware Defenses | 10.1 Deploy and maintain anti-malware software | IG1 | PARTIAL | Developer laptop: macOS XProtect + manual vigilance | Third-party AV planned |
| 10.2 Configure automatic anti-malware updates | IG1 | PARTIAL | macOS automatic updates enabled | System AV auto-updates | |
| 10.7 Use behavior-based anti-malware | IG3 | NO | Not implemented | Planned for 2027 | |
| 11: Data Recovery | 11.1 Establish data recovery process | IG1 | YES | Backup_Recovery_Policy.md, Git history | Documented |
| 11.2 Perform automated backups | IG1 | YES | S3 cross-region replication (real-time), Git | Automated | |
| 11.3 Protect recovery data | IG1 | YES | S3 versioning, Git signed commits | Protected | |
| 11.4 Establish isolated data backups | IG2 | YES | GitHub Pages separate from AWS primary | Isolated secondary deployment | |
| 12: Network Infrastructure Management | 12.1 Ensure network infrastructure is up-to-date | IG1 | N/A | No managed network infrastructure | Cloud-managed |
| 12.2 Establish network infrastructure management process | IG2 | YES | CloudFront security policy, Route 53 config | Documented in ARCHITECTURE.md | |
| 12.8 Manage DNS infrastructure | IG2 | YES | Route 53 with health checks, DNSSEC planned | Managed by AWS | |
| 13: Network Monitoring and Defense | 13.1 Centralize security event alerting | IG2 | YES | GitHub Security Advisories, Dependabot, CodeQL alerts | Centralized in GitHub Security tab |
| 13.3 Deploy network intrusion detection | IG3 | PARTIAL | CloudFront request metrics, WAF planned 2027 | Basic anomaly detection | |
| 13.6 Collect network traffic flow logs | IG2 | YES | CloudFront access logs, S3 server access logs | Configured | |
| 14: Security Awareness and Skills Training | 14.1 Establish security awareness program | IG1 | YES | CEO maintains security certifications, ISMS policies | Self-directed continuous learning |
| 14.6 Train workforce on recognizing phishing | IG1 | N/A | Single-person company | Not applicable | |
| 15: Service Provider Management | 15.1 Establish service provider management process | IG1 | YES | Third_Party_Management.md | Documented supplier assessment |
| 15.2 Establish service provider contracts | IG1 | YES | GitHub ToS, AWS ToS, Anthropic ToS | Contracts in place | |
| 16: Application Software Security | 16.1 Establish application security processes | IG1 | YES | Secure_Development_Policy.md | Documented SDLC |
| 16.2 Establish application inventory | IG1 | YES | Asset Register, package.json | Complete | |
| 16.3 Perform root cause analysis | IG2 | YES | Post-incident RCA template in BCPPlan.md | Template provided | |
| 16.8 Separate production and non-production systems | IG2 | YES | Branch-based dev, separate Pages deployment | Separated | |
| 16.9 Train developers in application security concepts | IG2 | YES | CEO is security architect by expertise | Implemented | |
| 16.10 Apply secure design principles in application architectures | IG2 | YES | Defense-in-depth, least privilege, static-first | Core architectural principle | |
| 16.11 Leverage vetted modules and services | IG2 | YES | npm known-good packages, GitHub Actions marketplace | SHA-pinned, Dependabot monitored | |
| 16.12 Implement code-level security checks | IG2 | YES | CodeQL, ESLint security rules, HTMLHint | Every PR | |
| 16.13 Conduct application penetration testing | IG3 | YES | Manual review + OWASP ZAP DAST (.github/workflows/zap-scan.yml, weekly + on-demand) | Automated active scans against production | |
| 17: Incident Response Management | 17.1 Designate personnel for incident response | IG1 | YES | CEO: designated IR coordinator | Documented in BCPPlan.md |
| 17.2 Establish incident response process | IG1 | YES | ISMS IRP, BCPPlan.md IR Playbooks | IR-PB-001/002/003 | |
| 17.3 Test incident response process | IG2 | PARTIAL | Annual BCP test includes IR scenarios | Quarterly BCP test planned | |
| 17.4 Train workforce on incident response | IG1 | N/A | Single-person company | CEO as sole responder | |
| 17.5 Evaluate lessons learned | IG2 | YES | Post-incident review in all IR playbooks | Documented | |
| 17.6 Define metrics for incident response | IG2 | YES | MTTP, RTO, RPO metrics in SECURITY_ARCHITECTURE.md | Tracked | |
| 18: Penetration Testing | 18.1 Establish a penetration testing program | IG2 | YES | OWASP ZAP active scans (weekly + on-demand) via .github/workflows/zap-scan.yml; rules baseline .zap/rules.tsv; reports retained 90 days | Automated DAST live |
| 18.2 Perform periodic external penetration tests | IG3 | PARTIAL | External pen test planned 2027 | Budgeted for 2027 | |
| 18.3 Remediate penetration test findings | IG2 | YES | Process documented; applied to CodeQL findings | Remediation process active |
CIS Controls IG1 Summary: 35/35 applicable controls implemented (100%)
CIS Controls IG2 Summary: 28/35 applicable controls implemented (80%)
CIS Controls IG3 Summary: 3/10 applicable controls implemented (30%) โ IG3 not a current target
Riksdagsmonitor's cyber supply chain is documented in the Third Party Management Policy (ISMS-PUBLIC) and mapped here:
Critical Suppliers Tier 1 (Platform-Level Dependency):
GitHub โ Source control, CI/CD, GitHub Pages hosting, GitHub Actions
AWS โ CloudFront CDN, S3 multi-region, Route 53 DNS
Supplier Tier 2 (Service-Level Dependency): 3. Anthropic (via GitHub Copilot) โ Claude Sonnet 4.6 AI model
Supplier Tier 3 (Component-Level Dependencies): 5. npm ecosystem โ JavaScript dependencies
Vetting Criteria for New Dependencies:
| Criterion | Requirement | Tool |
|---|---|---|
| Popularity | >100K weekly npm downloads or GitHub major org | Manual review |
| Maintenance | Active maintenance, commits within 12 months | GitHub repo check |
| Security history | No critical CVEs unpatched in last 12 months | npm audit, OSS Index |
| License | OSS license compatible with MIT (our license) | License checker |
| SBOM availability | Preferred for critical dependencies | GitHub SBOM feature |
| Signature | Provenance attestation preferred | npm provenance |
# Example: SHA-pinned GitHub Actions (from workflows)
- uses: actions/checkout@v4 # SHA: abc123...
- uses: step-security/harden-runner@v2 # SHA: def456...
- uses: github/codeql-action/init@v3 # SHA: ghi789...
SHA Pinning Policy:
@latest or floating version references permittedDependabot is configured in .github/dependabot.yml with:
# Integrated into CI/CD pipeline (GitHub Actions):
npm audit --audit-level=high # Blocks pipeline on high+ CVEs
npm audit --json > audit-report.json # Archive audit results
Audit gates:
critical: Blocks deployment immediatelyhigh: Blocks deployment + creates Dependabot PRmoderate: Creates advisory, does not blocklow: Logged only| Control | Implementation | Status |
|---|---|---|
| SHA pinning all actions | All actions pinned to commit SHA | Active |
| Egress control | step-security/harden-runner on all jobs | Active |
| Least privilege tokens | Per-job permissions: blocks | Active |
| Read-only token by default | GITHUB_TOKEN permissions default read | Active |
| No secret exposure | Secrets masked in logs, not passed to forks | Active |
| SLSA provenance | Build provenance via GitHub SLSA action | Active |
| Sigstore signing | Artifacts signed via Sigstore | Active |
| Dependency review | actions/dependency-review-action on PRs | Active |
Status: Planned (Target: Q3 2026) โ Article-level SHA-256 hashing is not yet implemented in the content generation pipeline. The design below documents the planned approach. Currently, content integrity is assured via Git commit history, SLSA provenance attestation, and Sigstore artifact signing.
Planned Hash Generation Process (not yet implemented):
<!-- Planned article metadata format (not yet in production) -->
<!-- content-hash: sha256:a3f5c8d2e1b4... -->
<!-- generated-at: 2026-02-25T02:15:00Z -->
<!-- pipeline-run: github.com/Hack23/riksdagsmonitor/actions/runs/12345 -->
<!-- sources: riksdag-api:2024/25, cia-export:2026-02-24 -->
| Control | Implementation | Status |
|---|---|---|
| SLSA provenance | Build provenance via GitHub SLSA action โ covers the full build artifact | Active |
| Sigstore signing | Build artifacts signed via Sigstore transparency log | Active |
| Git commit SHA | Immutable reference to exact content state; all pushes require GitHub authentication | Active |
| Branch protection | Direct pushes to main blocked; all changes require PR and CI green | Active |
| Dependency review | actions/dependency-review-action on all PRs | Active |
| Article-level SHA-256 | Per-article hash in HTML comment metadata | Planned (Q3 2026) |
main branch require authenticated push (GitHub authentication)| Detection Method | Trigger | Response | Status |
|---|---|---|---|
| SLSA attestation failure | GitHub Actions security job | Block deployment, alert CEO | Active |
| Unauthorized commit to main | GitHub branch protection | Block push, audit log alert | Active |
| Secret scanning match | GitHub Secret Scanning | Immediate block, credential rotation | Active |
| Unexpected file in deployment | Deployment diff review | Manual review gate | Active |
| SHA-256 hash mismatch | Automated integrity check | IR-PB-001 (Content Tampering) | Planned (Q3 2026) |
stateDiagram-v2
[*] --> Created
Created --> Active : Stored in GitHub Secrets
Active --> Expiring : Age 60+ days warning
Expiring --> Rotating : 90-day policy triggered
Rotating --> DualActive : New key created
DualActive --> Updated : GitHub Secret updated
Updated --> Active : Old key revoked
Active --> Compromised : Security event
Compromised --> Revoked : Immediate revocation
Revoked --> [*]
| Credential | Storage | Rotation Period | Access Level | Emergency Contact |
|---|---|---|---|---|
| GitHub Copilot agent token | GitHub-managed runtime token | Per GitHub platform policy | Agentic workflow scope only | GitHub Support |
| GitHub PAT (if used) | GitHub Secrets | 90 days | Minimal required scopes | GitHub Support |
| AWS IAM Access Key | GitHub Secrets | 90 days | Least privilege IAM policy | AWS Support |
| MCP Server API Keys | GitHub Secrets | Per provider policy | Read-only data access | Provider support |
90-Day Rotation Policy (all credentials):
Exception handling:
Secrets storage:
Secret naming convention:
GITHUB_TOKEN # GitHub-managed workflow token
AWS_ACCESS_KEY_ID # AWS IAM (if applicable)
AWS_SECRET_ACCESS_KEY # AWS IAM secret
MCP_RIKSDAG_API_KEY # riksdag-regering-mcp (if auth required)
P1 Trigger: Credential suspected compromised
| KPI | Target | Measurement Method | Review Frequency | Alert Threshold |
|---|---|---|---|---|
| Mean Time to Patch (MTTP) - Critical | < 7 days | Dependabot PR creation to merge | Weekly | > 5 days = amber; > 7 days = red |
| Mean Time to Patch (MTTP) - High | < 30 days | Dependabot PR creation to merge | Monthly | > 21 days = amber; > 30 days = red |
| Mean Time to Patch (MTTP) - Medium | < 90 days | Manual tracking | Quarterly | > 60 days = amber; > 90 days = red |
| Dependency Vulnerability Count - Critical | 0 | GitHub Security tab | Daily | > 0 = immediate alert |
| Dependency Vulnerability Count - High | < 5 | GitHub Security tab | Weekly | > 3 = amber; > 5 = red |
| CodeQL Scan Pass Rate | 100% | GitHub Actions success rate | Per commit | < 100% = immediate investigation |
| Dependabot Scan Pass Rate | 100% | Dependabot active | Daily | Disabled = immediate alert |
| Secret Scanning Pass Rate | 100% | GitHub Secret Scanning active | Continuous | Any detection = P1 incident |
| OpenSSF Scorecard Score | >= 8.0/10 | Scorecard monthly run | Monthly | < 7.5 = amber; < 7.0 = red |
| Platform Uptime | >= 99.9% | AWS CloudWatch / external monitoring | Monthly | < 99.5% = incident investigation |
| Origin Failover RTO | < 30 seconds | Quarterly failover test | Quarterly | > 30s = BCPPlan update required |
| DNS Failover RTO | < 15 minutes | Semi-annual DNS test | Semi-annual | > 20 min = Route 53 config review |
| Content Generation Success Rate | >= 95% | GitHub Actions pipeline results | Weekly | < 90% = pipeline investigation |
| Content Integrity Check Rate | 100% | SHA-256 validation in pipeline | Per article | < 100% = IR-PB-001 triggered |
| Incident Mean Time to Detect (MTTD) | < 4 hours | Time from event to detection | Per incident | > 4 hours = monitoring gap analysis |
| Incident Mean Time to Contain (MTTC) | < 4 hours | Time from detection to containment | Per incident | > 4 hours = playbook update |
| SLSA Attestation Success Rate | 100% | Build provenance generation | Per deploy | < 100% = block deployment |
| Category | Current Status | Target | Trend |
|---|---|---|---|
| Vulnerability Management | 0 Critical, 0 High open | 0 Critical, <5 High | Stable |
| Scan Coverage | 100% CodeQL, 100% Dependabot | 100% both | Stable |
| Security Score | 8.2/10 OpenSSF | >= 8.0/10 | Stable |
| Availability | 99.999% (YTD) | >= 99.9% | Exceeding |
| Patch Compliance | MTTP Critical < 7 days | < 7 days | On Target |
| Content Integrity | 100% hashed | 100% | Stable |
| Credential Rotation | On 90-day policy | 90-day | Compliant |
| Incident Response | Playbooks documented | Tested quarterly | Planned |
Reporting Cadence:
This section documents key security architecture decisions, the options considered, and the rationale for each choice. This record provides audit evidence and supports future architecture reviews.
| Field | Value |
|---|---|
| Decision Date | 2023-01-01 (founding) |
| Status | Active |
| Decision Maker | James Pether Sรถrling, CEO |
| Decision | Implement Riksdagsmonitor as 100% static HTML/CSS/JavaScript with no server-side code |
| Options Considered | Option A: Static HTML (chosen); Option B: Next.js SSR; Option C: WordPress; Option D: Django/Python backend |
| Rationale | Static HTML eliminates entire classes of vulnerabilities: no SQL injection, no server-side code injection, no session management vulnerabilities, no server process to compromise. The attack surface is reduced to TLS configuration and CDN security, both managed by proven cloud providers. |
| Security Impact | POSITIVE: Removes 6 of 10 OWASP Top 10 risks from scope (A1 injection, A2 broken auth, A4 insecure design, A5 security misconfig, A6 vulnerable components, A7 auth failures) |
| Tradeoffs | Limits real-time features, no user accounts, no search (mitigated by client-side search in roadmap) |
| Review Trigger | If requirement for authenticated user features arises |
| Field | Value |
|---|---|
| Decision Date | 2023-01-01 |
| Status | Active |
| Decision | Use GitHub Pages as the source-of-truth deployment target, with AWS CloudFront as CDN and performance layer |
| Options Considered | Option A: GitHub Pages + CloudFront (chosen); Option B: Netlify; Option C: Vercel; Option D: AWS S3 + CloudFront only |
| Rationale | GitHub Pages provides free, reliable hosting with automatic HTTPS and deep integration with GitHub Actions CI/CD. CloudFront provides global CDN, DDoS protection, custom domain, and origin failover. Dual deployment provides DR without additional cost. |
| Security Impact | POSITIVE: GitHub handles TLS certificate management, HSTS, and platform security. CloudFront provides WAF-ready edge security. No server credentials needed. |
| Tradeoffs | Dependency on GitHub and AWS availability (mitigated by failover design) |
| Review Trigger | If GitHub Pages SLA drops below 99.9% or pricing changes significantly |
| Field | Value |
|---|---|
| Decision Date | 2024-06-01 |
| Status | Active |
| Decision | Require step-security/harden-runner on all GitHub Actions workflows with egress-policy: audit |
| Options Considered | Option A: harden-runner (chosen); Option B: No egress control; Option C: Custom network policies |
| Rationale | Supply chain attacks via GitHub Actions (e.g., SolarWinds-style) are a real threat. harden-runner intercepts all network calls from the runner, logs them to audit trail, and can block unauthorized egress. This provides visibility and control over what the CI/CD pipeline contacts. |
| Security Impact | POSITIVE: Detects and can block unauthorized supply chain exfiltration. Provides audit trail for all CI/CD network activity. Aligns with SLSA Level 2+ requirements. |
| Tradeoffs | Slight performance overhead per job (< 5 seconds). Requires explicit allowlist for legitimate domains. |
| Review Trigger | Annually or when new workflow dependencies added |
| Field | Value |
|---|---|
| Decision Date | 2024-06-01 |
| Status | Active |
| Decision | Implement SLSA Level 2+ build provenance for all production deployments using GitHub SLSA action and Sigstore |
| Options Considered | Option A: SLSA + Sigstore (chosen); Option B: No provenance; Option C: Custom signing |
| Rationale | SLSA (Supply chain Levels for Software Artifacts) provides tamper-evident build provenance. In the event of a supply chain compromise, SLSA provenance enables forensic analysis of what was built, when, from what source, and by what process. Sigstore provides a public transparency log for all signatures. |
| Security Impact | POSITIVE: Enables supply chain attack detection and forensic investigation. Demonstrates build integrity to users. Aligns with CRA Annex I integrity requirements. |
| Tradeoffs | Minor additional build time (~30 seconds). Requires Sigstore account and transparency log entries. |
| Review Trigger | If SLSA Level 3 (hermetic builds) requirements are added |
| Field | Value |
|---|---|
| Decision Date | 2025-01-01 |
| Status | Active |
| Decision | Implement mandatory 90-day rotation for all API credentials, with automated reminder system |
| Options Considered | Option A: 90-day rotation (chosen); Option B: Annual rotation; Option C: No rotation policy; Option D: 30-day rotation |
| Rationale | NIST SP 800-63B recommends periodic credential rotation for machine credentials. 90 days balances security (limits exposure window if credential is silently compromised) against operational burden. Annual rotation creates too-long exposure windows. 30-day rotation creates excessive operational burden for a solo operator. |
| Security Impact | POSITIVE: Limits credential compromise exposure window to 90 days. Aligns with ISO 27001:2022 control A.9.4.3 and CIS Control 6. |
| Tradeoffs | Operational overhead for rotation (estimated 30 minutes per rotation cycle). Risk of service disruption if rotation not completed before expiry. |
| Review Trigger | If automated credential rotation becomes available via provider |
| Field | Value |
|---|---|
| Decision Date | 2023-01-01 (founding) |
| Status | Active |
| Decision | Architect Riksdagsmonitor to collect zero Personally Identifiable Information from users: no cookies, no analytics, no user accounts |
| Options Considered | Option A: Zero PII (chosen); Option B: Cookie-based analytics (Google Analytics); Option C: Anonymous analytics (Plausible); Option D: Full user accounts |
| Rationale | Processing PII creates GDPR obligations, privacy risk, and potential breach liability. A civic transparency platform should model privacy by design. Public political data requires zero PII to fulfill its mission. Zero PII architecture eliminates entire GDPR compliance burden and aligns with CRA Article 13 data minimization. |
| Security Impact | POSITIVE: Eliminates GDPR data breach risk, no PII exposure possible, reduces legal liability, simplifies DPA. Aligns with ISO 27001:2022 A.5.34. |
| Tradeoffs | No user personalization, no understanding of actual usage patterns, no A/B testing capability. |
| Review Trigger | If user accounts become necessary for API access tier |
| ADL ID | Decision | Security Impact | Status |
|---|---|---|---|
| ADL-001 | Static HTML architecture | Eliminates 6 OWASP Top 10 risks | Active |
| ADL-002 | GitHub Pages + CloudFront | TLS management, CDN DDoS protection | Active |
| ADL-003 | harden-runner egress control | Supply chain attack detection | Active |
| ADL-004 | SLSA + Sigstore provenance | Tamper-evident build chain | Active |
| ADL-005 | 90-day credential rotation | Limits compromise exposure | Active |
| ADL-006 | Zero PII architecture | Eliminates GDPR breach risk | Active |
Riksdagsmonitor relies on major cloud providers whose security certifications extend platform-level protections:
| Provider | Certifications | Relevant Services | Evidence |
|---|---|---|---|
| GitHub (Microsoft) | ISO 27001, SOC 2 Type II, SOC 3, PCI DSS, CSA STAR | Source control, CI/CD, GitHub Pages, Actions | github.com/security |
| Amazon Web Services | ISO 27001, SOC 1/2/3, PCI DSS, FedRAMP, CSA STAR | CloudFront CDN, S3, Route 53 | aws.amazon.com/compliance |
| Anthropic (via GitHub Copilot) | SOC 2 Type II (provider), ISO 27001 (provider) | Claude Sonnet 4.6 AI model | via GitHub Copilot / Anthropic provider documentation |
flowchart TD
TOTAL_SECURITY[Total Security Posture]
TOTAL_SECURITY --> HACK23[Hack23 AB Responsibility]
TOTAL_SECURITY --> GITHUB[GitHub Responsibility]
TOTAL_SECURITY --> AWS[AWS Responsibility]
HACK23 --> HACK23_CODE[Source code security]
HACK23 --> HACK23_ACCESS[Access credentials and MFA]
HACK23 --> HACK23_CONTENT[Content integrity]
HACK23 --> HACK23_DEPS[Dependency selection and patching]
HACK23 --> HACK23_CONFIG[Workflow and deployment configuration]
HACK23 --> HACK23_ISMS[ISMS policies and procedures]
GITHUB --> GITHUB_PLAT[Platform security and availability]
GITHUB --> GITHUB_TLS[HTTPS and TLS certificate management]
GITHUB --> GITHUB_AUDIT[Audit logging infrastructure]
GITHUB --> GITHUB_RUNNER[Actions runner infrastructure]
AWS --> AWS_CDN[CloudFront infrastructure security]
AWS --> AWS_S3[S3 data center physical security]
AWS --> AWS_DNS[Route 53 DNS infrastructure]
AWS --> AWS_DDOS[DDoS protection at network layer]
style HACK23 fill:#4caf50,color:#000000
style GITHUB fill:#2196f3,color:#ffffff
style AWS fill:#ff9800,color:#000000
| Supplier | Risk Type | Inherent Risk | Controls | Residual Risk | Review |
|---|---|---|---|---|---|
| GitHub | Platform unavailability | HIGH | CloudFront failover, GitHub SLA monitoring | LOW | Quarterly |
| GitHub | Credential compromise | HIGH | MFA enforced, branch protection, least privilege | LOW | Annual |
| AWS CloudFront | CDN outage | MEDIUM | GitHub Pages failover, multi-region S3 | LOW | Quarterly |
| GitHub Copilot / Anthropic | AI API unavailability | MEDIUM | Graceful degradation to template articles; workflow retry and PR review gate | LOW | Quarterly |
| riksdag-regering-mcp | Data pipeline failure | MEDIUM | Local caching, stale data banner | LOW | Per release |
| npm registry | Supply chain attack | HIGH | package-lock.json pinning, Dependabot | MEDIUM | Daily automated |
| Riksdag API | API changes breaking data pipeline | MEDIUM | Schema versioning, monitoring | MEDIUM | Quarterly |
Riksdagsmonitor's overall security posture as of 2026-02-25:
| Security Domain | Maturity Level | Key Strength | Key Gap |
|---|---|---|---|
| Attack Surface | Level 5 - Optimized | Zero server-side code | Client-side search expansion planned |
| Identity and Access | Level 4 - Managed | MFA everywhere, least privilege | No automated rotation yet |
| Supply Chain | Level 4 - Managed | SHA pinning, SLSA, Dependabot | SBOM automation pending |
| Vulnerability Management | Level 4 - Managed | Automated scanning, MTTP tracked | External pentest pending |
| Incident Response | Level 3 - Defined | Playbooks documented | Testing cadence to improve |
| Compliance | Level 4 - Managed | Multi-framework alignment | ISO 27001 cert pending |
| Business Continuity | Level 4 - Managed | Dual-deployment, RTO <30s | Annual DR exercise planned |
| Monitoring | Level 3 - Defined | GitHub Security, OpenSSF | SIEM integration planned 2028 |
๐ Document Owner: James Pether Sรถrling, CEO & CISO
๐ Version: 2.4
๐
Last Updated: 2026-05-06 (UTC)
โ
Approved by: James Pether Sรถrling, CEO
๐ Review Cycle: Annual
โฐ Next Review: 2027-05-06
๐ข Owner: Hack23 AB (Org.nr 5595347807)
๐ค Distribution: Public
๐ท๏ธ Classification:
Effective: 2026-04-24 ยท Authoritative hub:
analysis/imf/README.mdยทanalysis/imf/agentic-integration.mdยทanalysis/imf/indicators-inventory.jsonยทanalysis/imf/data-dictionary.mdยท.github/aw/ECONOMIC_DATA_CONTRACT.md
flowchart LR
subgraph Trusted["Trust Boundary โ Riksdagsmonitor build/news pipeline"]
Worker[News-* workflow worker ยท Node 26 ยท tsx scripts/imf-fetch.ts]
Cache[(analysis/imf/ + analysis/daily/*/economic-data.json ยท vintage-tagged ยท SHA-256 pinned)]
Audit[Workflow logs ยท news-* runs]
end
subgraph Public["Public-Internet ยท IMF Open APIs (Datamapper unauth ยท SDMX subscription-key)"]
Datamapper[www.imf.org/external/datamapper/api/v1]
SDMX[api.imf.org]
end
Worker -- HTTPS ยท TLS 1.3 --> Datamapper
Worker -- HTTPS ยท TLS 1.3 --> SDMX
Datamapper -. JSON payload .-> Worker
SDMX -. SDMX-JSON payload .-> Worker
Worker --> Cache
Worker --> Audit
| Attribute | Value | Authority |
|---|---|---|
| Confidentiality | PUBLIC | IMF data is public macro statistics |
| Integrity target | HIGH | SHA-256 pin + vintage-label + supersedes-chain |
| Availability target | STANDARD | Degrades to last cached vintage on outage |
| RTO | 24h | BCPPlan ยงIMF |
| RPO | N/A | Read-only public data |
| GDPR scope | OUT | No personal data; DPIA short-circuit |
| Licence | Attribution required | Auto-emitted in article footer |
| Control | Implementation | Framework mapping |
|---|---|---|
| Egress allow-list | www.imf.org, api.imf.org only | ISO A.13.1 / NIST PR.AC-5 / CIS 13.4 |
| Payload integrity | SHA-256 pin per (dataflow, indicator, country, vintage) | ISO A.8.2 / NIST PR.DS-6 / CIS 3.11 |
| Vintage discipline | Reject >6-month payloads without staleness annotation | ISO A.8.10 / NIST PR.DS-1 / CIS 3.5 |
| Rate-limit guard | โค30 req/min; exponential back-off | ISO A.13.1 / NIST PR.AC-4 / CIS 4.7 |
| Provenance audit | economicProvenance block in every article front-matter | ISO A.5.28 / NIST DE.AE-3 / CIS 8.2 |
| Supply-chain | Scripts in-repo; reviewed; harden-runner egress audit | ISO A.5.21 / NIST PR.IP-2 / CIS 16.11 |
Egress hosts (allow-list): www.imf.org (Datamapper REST ยท WEO/FM, unauthenticated), api.imf.org (SDMX 3.0 REST ยท IFS/BOP/DOTS/GFS/PCPS/ER/MFS_IR/MFS_PR, subscription-key authenticated via the Azure APIM Ocp-Apim-Subscription-Key header / IMF_SDMX_SUBSCRIPTION_KEY secret). Both HTTPS-only; payloads are public macro statistics with no PII.
Canonical rule. Every economic claim in a Riksdagsmonitor article cites an IMF dataflow first; World Bank citations are reserved for governance, environment and social residue (the classes IMF does not publish). SCB is the Swedish-specific ground truth layer. See ECONOMIC_DATA_CONTRACT.md v2.1 for the banned-phrase list and vintage discipline (>6 mo โ annotation).
Statskontoret is a read-only public-data integration using in-repository TypeScript code and the existing npm dependency graph. It is intentionally not configured as an MCP server; workflows invoke tsx scripts/statskontoret-fetch.ts via the bash tool.
| Control area | Statskontoret control |
|---|---|
| Network egress | Allow only HTTPS to www.statskontoret.se for this provider. |
| Authentication | None required; no tokens or secrets transmitted. |
| Input validation | Resource classification, URL normalisation, HTML entity decoding, XLSX workbook structure checks, CSV ZIP file filtering. |
| Integrity | Persisted JSON plus .meta.json provenance sidecars with source/dataset/artifact/fetch timestamp. |
| Availability | 15s client timeout and optional-enrichment fallback to cached artifacts. |
| Supply chain | Parser code is local TypeScript; ZIP/XLSX parsing uses jszip under npm lock/SBOM and advisory review. |
| Privacy | Public authority and aggregate budget records only; no private-person or credential data. |
Security classification: PUBLIC / High Integrity / Medium-High Availability. Mapped controls: ISO 27001 A.5.23 (cloud/service use), A.8.9 (configuration management), A.8.12 (data leakage prevention by design), A.8.20 (network security), NIST CSF 2.0 ID.IM / PR.DS / PR.PS, CIS Controls 4, 8, 12 and 16.
This section documents the security controls governing the AI-driven political intelligence analysis pipeline.
Riksdagsmonitor's political intelligence pipeline introduces a unique attack surface: 39 analysis templates and 18 methodologies processed by AI agents (Claude Sonnet 4.6) within 14 agentic workflows. These templates define the analytical structure that shapes all output articles. A compromise of the template content or a bypass of the structural validation gate could lead to biased, fabricated, or manipulated political intelligence output.
flowchart TD
subgraph "Trusted Control Plane (Git-reviewed)"
TMPL["39 Analysis Templates<br/>analysis/templates/*.md"]
METH["18 Methodologies<br/>analysis/methodologies/*.md"]
GATE["Analysis Gate<br/>scripts/agentic/analysis-gate.ts"]
REFL["Methodology Reflection Validator<br/>scripts/validate-methodology-reflection.ts"]
PROMPT["Prompt Modules<br/>.github/prompts/"]
end
subgraph "AI Agent Runtime (Sandboxed)"
AGENT["Claude Sonnet 4.6<br/>(14 agentic workflows)"]
end
subgraph "Output (PR-Gated)"
ART["Analysis Artifacts<br/>analysis/daily/YYYY-MM-DD/"]
NEWS["News Articles<br/>content/"]
end
TMPL --> AGENT
METH --> AGENT
PROMPT --> AGENT
AGENT --> ART
ART --> GATE
ART --> REFL
GATE -->|pass| NEWS
GATE -->|fail| REJECT["โ Workflow fails"]
Implementation: scripts/agentic/analysis-gate.ts ยท Specification: .github/prompts/05-analysis-gate.md
The analysis gate is a fail-closed structural-integrity control that validates all 23 required analysis artifacts before any article content proceeds to PR review. It operates as Layer 0 of the safe-output pipeline (pre-sanitisation validation).
| Check | Control | What It Validates | Bypass Resistance |
|---|---|---|---|
| 1 | Artifact existence | All 23 files present and non-empty | Typed filename set; recursive scan; size > 0 |
| 2 | Per-document coverage | Family E vs manifest | dok_id regex validation; cross-ref to artifact inventory |
| 3 | No stub placeholders | Recursive .md scan for known stub phrases | Pattern list version-controlled; collectMdFilesRecursive() |
| 4 | Evidence citations | SWOT + significance scoring contain evidence | EVIDENCE_PATTERN regex; real source IDs required |
| 5 | Mermaid diagrams | Colour config + node labels in diagrams | MERMAID_NODE_RE matches [], (), {} label shapes |
| 6 | Pass-2 evidence | Mtime or pass1/ snapshot diff | PASS2_MTIME_THRESHOLD_MS = 180_000 (3 min) |
| 7 | Family C structure | Strategic extension artifacts well-formed | Typed interface validation |
| 8 | Family D structure | Electoral & domain lens artifacts well-formed | Typed interface validation |
| 9 | PIR status sidecar | Priority Intelligence Requirements file present | JSON schema check |
| 9b | Statskontoret evidence | Implementation-feasibility references Statskontoret | RECOGNISED_AGENCIES list (12 entries) |
Test coverage: Per-check suites in tests/agentic/gate-checks/, shared-helper suites in tests/agentic/gate-shared/, and orchestrator scenarios in tests/agentic/analysis-gate-integration.test.ts.
Failure mode: If any check fails, the entire workflow run fails โ no article is generated and no PR is created. This prevents partial or manipulated output from reaching the human-review gate.
Implementation: scripts/validate-methodology-reflection.ts
Validates that each methodology-reflection.md artifact meets the integrity-of-process contract:
| Validation | Purpose |
|---|---|
| Required H2 sections (8) | Ensures complete analytical reflection |
| Minimum byte threshold (scaled by period-scope) | Prevents trivial/empty reflections |
Confidence labels ([HIGH], [MEDIUM], [LOW]) | Enforces uncertainty acknowledgement |
| Upstream-watchpoint reconciliation table (Tier-C) | Cross-validates upstream data references |
All political data (MPs, votes, parties, speeches) is classified under the Hack23 CLASSIFICATION framework:
Horizon stratification limits which data classes can inform which forecast band:
| Horizon Band | Permitted Data Sources | Prohibited |
|---|---|---|
| T+72h (short-term) | Riksdag calendar, vote records, committee schedules | Future economic projections |
| T+7d (week-ahead) | Parliamentary schedule, government press releases | Speculative coalition analysis |
| T+30d (month-ahead) | IMF WEO projections, SCB statistics, government proposals | Election-cycle scenarios |
| T+90d โ T+365d (quarter/year) | All economic data, trend analysis, historical patterns | N/A |
| T+1460d (election-cycle) | Full scenario trees, coalition modelling | N/A โ all sources permitted |
Control: The prompt modules in .github/prompts/ encode horizon constraints. The analysis gate validates artifact structure matches the declared article type (from analysis/article-types.json).
AI-generated content must comply with OSINT operational standards:
dok_id (Riksdag document ID) or named data source[HIGH]/[MEDIUM]/[LOW] confidence markersReference: gh-aw Architecture Documentation ยท WORKFLOWS.md ยง gh-aw Security Architecture
Riksdagsmonitor's 14 agentic news workflows execute within GitHub Agentic Workflows (gh-aw) โ a purpose-built security runtime that enforces defense-in-depth through three independently enforceable trust layers. Each layer operates autonomously: a compromise of one layer does not bypass the protections of subsequent layers.
The gh-aw substrate provides hardware-enforced security boundaries that no agent code can override:
flowchart TD
subgraph VM["๐ฅ๏ธ Ephemeral Runner VM"]
subgraph Container["๐ณ Agent Container (chroot)"]
AGENT["๐ค AI Agent Process"]
FS["๐ Read-only Filesystem"]
end
subgraph AWF["๐งฑ Agent Workflow Firewall"]
IPTABLES["iptables (REDIRECT โ Squid)"]
SQUID["Squid Proxy (domain allowlist)"]
end
subgraph MCPGW["๐ณ MCP Gateway"]
MCP1["riksdag-regering<br/>(HTTP hosted)"]
MCP2["scb<br/>(node:26-alpine)"]
MCP3["world-bank<br/>(node:26-alpine)"]
end
PROXY["๐ API Proxy<br/>(token-scoped)"]
end
AGENT -->|"HTTP/HTTPS"| IPTABLES
IPTABLES -->|"redirect"| SQUID
SQUID -->|"allowlisted only"| INTERNET["๐ Internet<br/>(17 domains)"]
SQUID -->|"non-allowlisted"| DROP["โ DROP"]
AGENT -->|"MCP calls"| MCPGW
AGENT -->|"GitHub API"| PROXY
style VM fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style AWF fill:#1a237e,color:#fff
style Container fill:#e8f5e9,stroke:#2e7d32
style DROP fill:#b71c1c,color:#fff
| Component | Security Function | Enforcement Mechanism |
|---|---|---|
| ๐ฅ๏ธ Ephemeral Runner VM | Complete isolation per workflow run; no state persists between runs | GitHub-managed infrastructure; VM destroyed after run completes |
| ๐งฑ Agent Workflow Firewall (AWF) | Network containment โ all egress filtered through domain allowlist | iptables REDIRECT rules route HTTP(S) through Squid proxy; DROP policy for non-matching traffic |
| ๐ณ MCP Gateway | Tool isolation โ each MCP server runs in a separate Docker container with its own network namespace | Per-container: tool allowlisting, network controls, secret injection via environment variables only |
| ๐ API Proxy | Token scoping โ GitHub API access limited to declared permissions | Token automatically scoped to workflow-declared permissions: block; no privilege escalation possible |
Riksdagsmonitor substrate configuration:
WORKFLOWS.md ยง Network egress allow-list)riksdag-regering via HTTP, scb + world-bank in node:26-alpine containers)github, agentic-workflows, bash, playwright, repo-memory)Security enforced during gh aw compile before any workflow can execute:
flowchart LR
MD[".md source<br/>(human-authored)"] -->|"gh aw compile"| VALIDATE
subgraph VALIDATE["โ๏ธ Compile-Time Security Checks"]
S1["๐ Schema Validation<br/>(structure, permissions, triggers)"]
S2["๐ Expression Safety<br/>(allowlisted patterns only)"]
S3["๐ SHA Pinning<br/>(immutable action refs)"]
S4["๐ Scanner Suite<br/>(actionlint + zizmor + poutine)"]
S5["๐ Size Cap<br/>(โค 550 lines per prompt)"]
end
VALIDATE -->|"pass"| LOCK[".lock.yml<br/>(hardened, executable)"]
VALIDATE -->|"fail"| REJECT["โ Compilation rejected"]
style VALIDATE fill:#004d40,color:#fff
style REJECT fill:#b71c1c,color:#fff
| Control | What It Prevents | Detection Method |
|---|---|---|
| ๐ Schema Validation | Malformed workflows, excessive permissions, unsafe trigger patterns | JSON Schema validation against gh-aw workflow specification |
| ๐ Expression Allowlisting | Template injection via ${{ }} in shell commands | Static analysis of all expression usage; only safe patterns permitted |
| ๐ Action SHA Pinning | Supply chain attacks via tag-mutable action references | All uses: directives must reference full commit SHA (40 hex chars) |
| ๐ Security Scanners | Known workflow anti-patterns, vulnerable configurations | actionlint (syntax + security), zizmor (GitHub-specific), poutine (supply chain) |
| ๐ Prompt Module Size Cap | Prompt injection via oversized modules; unreviewed content | Hard 550-line limit per .github/prompts/*.md file |
| ๐ Lock File Integrity | Manual tampering with compiled workflows | .lock.yml regenerated from .md on every compile; manual edits overwritten |
Riksdagsmonitor compile-time controls:
compile-agentic-workflows.yml.lock.yml diff reviewed alongside .md source changesControls that govern what the AI agent can accomplish during execution:
flowchart TD
subgraph AGENT_JOB["๐ค Agent Job (read-only permissions)"]
AGENT["AI Agent"] -->|"produces"| ARTIFACTS["๐ฆ Buffered Artifacts"]
end
subgraph DETECTION["๐ต๏ธ Threat Detection Job (separate)"]
DL["Download artifacts"]
AI_SCAN["AI security analysis<br/>(secret leaks, malicious patches)"]
CONTENT["Content sanitisation<br/>(@mention, URI, HTML tags)"]
SECRETS["Secret redaction scan"]
DL --> AI_SCAN --> CONTENT --> SECRETS
end
subgraph SAFE_OUTPUTS["๐ค Safe Output Jobs"]
PR_CREATE["create_pull_request"]
COMMENT["add_comment"]
ISSUE["create_issue"]
end
ARTIFACTS -->|"workflow artifacts"| DL
SECRETS -->|"PASS verdict"| SAFE_OUTPUTS
SECRETS -->|"FAIL verdict"| BLOCKED["โ All outputs blocked"]
style AGENT_JOB fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
style DETECTION fill:#fff3e0,stroke:#e65100,stroke-width:2px
style SAFE_OUTPUTS fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style BLOCKED fill:#b71c1c,color:#fff
| Principle | Implementation |
|---|---|
| Agent has no write permissions | Agent job's permissions: block is read-only; cannot push commits, create PRs, or modify issues directly |
| Writes are buffered | All agent output stored as workflow artifacts (not direct GitHub API calls) |
| Separate execution context | Safe output jobs (create_pull_request, add_comment, create_issue) run in distinct jobs with write permissions |
| Threat detection gates outputs | Detection job must pass before any safe output job can execute |
| Check | What It Detects | Action on Detection |
|---|---|---|
| ๐ Secret leak scanning | API keys, tokens, credentials in agent output | Block all safe outputs; redact detected secrets |
| ๐ Malicious patch detection | Code changes that introduce vulnerabilities or backdoors | Block PR creation; alert maintainers |
| ๐ Policy violation | Output exceeds size limits, contains prohibited content, violates content policy | Block affected outputs |
| ๐ท๏ธ @mention neutralisation | Agent output containing GitHub @username mentions that could spam users | Convert @user โ @โuser (zero-width space injection) |
| ๐ URI filtering | Non-HTTPS URLs, untrusted domain links | Strip or convert to safe references |
| ๐ท๏ธ Bot trigger protection | Content that could trigger other bots/automations (e.g., /deploy, @dependabot merge) | Neutralise command patterns |
Controls which existing GitHub content the agent can read, based on trust level:
| Trust Level | Content Access | Example |
|---|---|---|
| Merged (highest) | Full access | Merged PR content, main branch files |
| Approved | Read access | Approved but unmerged PR content |
| Unapproved | Restricted | Pending PR content โ limited context |
| None | Blocked | External/unknown source content |
Pre-upload scanning of the /tmp/gh-aw working directory:
*** (e.g., ghp***)The following table maps how gh-aw's three-layer model integrates with Riksdagsmonitor's own security controls to create a comprehensive defense:
| gh-aw Layer | gh-aw Control | Riksdagsmonitor Extension | Combined Effect |
|---|---|---|---|
| ๐ L1 Substrate | AWF egress firewall | 17-domain allowlist (political data sources only) | Agent cannot exfiltrate data to arbitrary hosts |
| ๐ L1 Substrate | MCP container isolation | 3 containerised servers (scb, world-bank, riksdag) | Tool compromise contained to single container |
| โ๏ธ L2 Config | Schema validation | compile-agentic-workflows.yml CI gate | Invalid workflows cannot reach main branch |
| โ๏ธ L2 Config | SHA pinning | 100% pinning + Dependabot version updates | No supply chain tag-swap attacks possible |
| ๐ก๏ธ L3 Plan | SafeOutputs | Five-layer output validator (checks 1โ9b + methodology reflection) | AI output structurally validated before PR creation |
| ๐ก๏ธ L3 Plan | Threat detection | Analysis gate + OSINT tradecraft compliance | Domain-specific validation beyond generic security |
| ๐ก๏ธ L3 Plan | Content sanitisation | rehype-sanitize + Mermaid strict mode + URI filtering | No XSS, no script injection, no malicious links |
| ๐ก๏ธ L3 Plan | Secret redaction | Automatic pre-upload scan | No credentials leaked in analysis artifacts or articles |
Cross-reference: THREAT_MODEL.md ยงTB-PI series ยท
.github/workflows/README.mdยท gh-aw Architecture
The five-layer model governs all 14 agentic news workflows. Each layer is independent โ a bypass of one layer does not compromise the subsequent layers. This model extends gh-aw's Layer 3 (Plan-Level Trust) with domain-specific political intelligence validation.
flowchart TD
AGENT["AI Agent Output"] --> L1["Layer 1: Sanitisation<br/>(rehype-sanitize allow-list)"]
L1 --> L2["Layer 2: Schema Validation<br/>(artifact structure + YAML front-matter)"]
L2 --> L3["Layer 3: Policy Check<br/>(analysis gate checks 1โ9b)"]
L3 --> L4["Layer 4: Human Review<br/>(mandatory PR approval)"]
L4 --> L5["Layer 5: Merge & Deploy<br/>(branch protection rules)"]
L1 -->|"blocks <script>, <iframe>, handlers"| FAIL["โ Rejected"]
L2 -->|"missing fields / malformed YAML"| FAIL
L3 -->|"gate check failure"| FAIL
L4 -->|"reviewer rejects"| FAIL
| Layer | Control | Bypass Resistance | Failure Mode |
|---|---|---|---|
| 1. Sanitisation | rehype-sanitize allow-list blocks <script>, <iframe>, inline event handlers, javascript: URIs | Allow-list approach (not deny-list); Mermaid rendered in securityLevel: 'strict' | Malicious HTML stripped silently |
| 2. Schema Validation | YAML front-matter schema; artifact file structure; 23-file completeness | Typed TypeScript validators; JSON schema | Workflow fails with validation error |
| 3. Policy Check | Analysis gate (checks 1โ9b); methodology-reflection validator | Fail-closed; 88 unit tests; no partial pass | Workflow fails โ no PR created |
| 4. Human Review | Mandatory PR approval by repository maintainer | Branch protection rule; CODEOWNERS; cannot self-approve | PR blocked until approved |
| 5. Merge & Deploy | Signed commits; CI must pass; deploy via OIDC (no stored creds) | GitHub branch protection; SLSA provenance | Merge blocked if CI fails |
All agentic workflows execute behind a Squid proxy with domain allow-list enforcement and iptables rules that DROP all non-allowlisted outbound connections:
riksdagen.se, www.riksdagen.se, data.riksdagen.se, regeringen.se, www.regeringen.se, riksdag-regering-ai.onrender.com, api.scb.se, api.worldbank.org, www.imf.org, api.imf.org, data.imf.org, github.com, raw.githubusercontent.com, hack23.github.io, hack23.com, www.hack23.com, riksdagsmonitor.comstep-security/harden-runner egress audit| MCP Server | Authentication | Scope |
|---|---|---|
riksdag-regering | HTTPS (anonymous public API) | Read-only parliamentary data |
scb | Container-isolated; anonymous | Read-only statistics |
world-bank | Container-isolated; anonymous | Read-only indicators |
github | PAT (scoped to repository) | Repo read + PR write |
filesystem | Local (no network) | Working directory only |
memory | Local (no network) | Session-scoped KV store |
sequential-thinking | Local (no network) | No external access |
playwright | Local (headless) | No navigation outside allowlist |
| Attack Vector | Mitigation | Effectiveness |
|---|---|---|
| Indirect injection via Riksdag document titles | MCP returns structured JSON (not raw HTML); titles are data fields, not executable prompts | HIGH โ structured data pipeline |
| Poisoned methodology file | Version-controlled in Git; PR-reviewed; immutable once merged | HIGH โ Git integrity |
| Template manipulation | Templates in analysis/templates/ are PR-reviewed; changes require CEO approval per Change Management | HIGH โ change control |
| Cross-session data leakage | Each workflow run is stateless; repo-memory branch is append-only and reviewed | MEDIUM โ review-dependent |
| Model hallucination as injection vector | Analysis gate checks evidence citations; mandatory dok_id validation | HIGH โ structural validation |
| Provider | Transport | Auth | Schema Validation | Cache Integrity | Tamper Detection | Trust Level |
|---|---|---|---|---|---|---|
| IMF (Datamapper + SDMX) | HTTPS/TLS 1.3 | Anonymous | DatamapperResponse shape + finite-numeric + year parse-guard | analysis/data/imf/{indicator}/{country}.json | .meta.json sidecars (vintage, timestamp, hash) | PUBLIC / Read-only |
| SCB (MCP container) | HTTPS to api.scb.se | Anonymous | PxWeb JSON-stat2 schema | analysis/data/scb/{tableId}.json | .meta.json sidecars | PUBLIC / Read-only |
| World Bank (MCP container) | HTTPS to api.worldbank.org | Anonymous | JSON response schema | analysis/data/worldbank/{indicator}/{country}.json | .meta.json sidecars | PUBLIC / Read-only |
| Riksdag API | HTTPS to data.riksdagen.se | Anonymous | XML/JSON schema (dok_id format) | N/A (live API) | dok_id cross-validation | PUBLIC / Read-only |
| Riksbank | HTTPS | Anonymous | CSV/JSON schema | analysis/data/riksbank/ | .meta.json sidecars | PUBLIC / Read-only |
| Statskontoret | HTTPS to www.statskontoret.se | Anonymous | HTML/XLSX structure checks | analysis/data/statskontoret/ | .meta.json sidecars | PUBLIC / Read-only |
| Riksrevisionen | HTTPS | Anonymous | Report structure validation | analysis/data/rir/ | .meta.json sidecars | PUBLIC / Read-only |
Common controls across all providers:
| ๐ Platforms | ๐ฆ Open-Source Projects | ๐ก๏ธ Governance & Standards |
|---|---|---|
| ๐ณ๏ธ Riksdagsmonitor โ Swedish Parliament intelligence ๐ช๐บ EU Parliament Monitor โ European coverage ๐ต๏ธ Citizen Intelligence Agency โ political-data engine ๐ Hack23 AB โ corporate site ๐ฐ Hack23 Blog โ engineering & policy ๐ผ Hack23 on LinkedIn | ๐ณ๏ธ Hack23/riksdagsmonitor ๐ต๏ธ Hack23/cia ๐ช๐บ Hack23/euparliamentmonitor ๐ Hack23/european-parliament-mcp โ Hack23/cia-compliance-manager ๐ฅ Hack23/black-trigram ๐ Hack23/homepage | ๐ก๏ธ Hack23 ISMS-PUBLIC โ public ISMS ๐ Information Security Policy ๐ค AI Policy ๐งช Secure Development Policy ๐ฏ Threat Modeling Policy โ ๏ธ Vulnerability Management ๐ท๏ธ Classification Framework |
๐ณ๏ธ Empower citizens ยท ๐ Strengthen democratic accountability ยท ๐ต๏ธ Illuminate the political process
ยฉ 2008โ2026 Hack23 AB (Org.nr 559534-7807) ยท Maintainer: James Pether Sรถrling, CISSP CISM