All case studies

Case study 12 / 19

CSIRT Nusantara Regas Public Website

Public website of the company's Computer Security Incident Response Team: incident reporting guidance, RFC 2350 documents, PGP public key and the BSSN guide library, built as a hardened static Angular 22 site with no backend to attack.

Stack
Angular 22 · TypeScript · SCSS · Vitest · Nginx · Docker · CSP · TLS
Links
Live Site
CSIRT Nusantara Regas home page hero with the report-incident call to action and the list of reportable incident types

The problem

A CSIRT needs a public, trustworthy front door: how to report an incident, which channels are official, the team's RFC 2350 description and its PGP key. For a security team the site itself must not become an attack surface: no forms to abuse, no server-side code to exploit, and headers that hold up under scrutiny.

What I built

I built the site as a static Angular 22 single-page application with standalone components, signals and lazy routes, served by an unprivileged nginx container. Incident reports go by email, optionally PGP-encrypted, so there is no backend and nothing is stored. The production stack adds an edge nginx with TLS, HSTS, request and connection rate limits, GET and HEAD only, a read-only root filesystem, dropped capabilities and an internal network between edge and app. Content lives in typed configuration files: services, reporting steps, incident types, the guide library and the organisation's contact details.

In use

Live cyber threat map embedded on the home page inside a browser-styled frame
Live cyber threat map embedded on the home page inside a browser-styled frame
Guide library page with the BSSN incident-handling documents
Guide library page with the BSSN incident-handling documents
Contact page with the official channels and the office location map
Contact page with the official channels and the office location map

Architecture

Visitors hit a rate-limited edge nginx that terminates TLS and forwards only GET and HEAD to an unprivileged nginx serving the static Angular bundle with CSP headers. There is no backend: incident reports travel by email, the threat map is embedded from its provider, and the documents are static assets copied at build time.

CSIRT website architecture: incident reporters, constituency staff and peer CSIRTs reach a rate-limited TLS edge nginx, which proxies to an unprivileged nginx serving the static Angular 22 SPA with CSP headers; reports leave by email, and the threat map and static documents sit outside the site

Open the image for full size

Proof

  1. 01 Angular 22 zoneless application with OnPush components, signal inputs and native control flow; production builds enforce bundle budgets of 500 kB warning and 1 MB error.
  2. 02 CSP and security headers included from every nginx location, SPA fallback, gzip, cache rules and a health endpoint; the app container runs nginx-unprivileged on Alpine.
  3. 03 Production Compose with an edge proxy: TLS and HSTS, limit_req and limit_conn per address, only GET and HEAD forwarded, read-only rootfs and cap_drop ALL on both containers.
  4. 04 Accessibility built in: skip link, aria attributes on navigation, visible focus styles, aria-current on active links, and a responsive menu that turns child links into a dropdown or an accordion.
  5. 05 Legacy routes redirect to their new homes, every page sets its own title, and the embedded live threat map falls back to a link-out when the provider blocks framing.

Result

The CSIRT has a single public reference for reporting and verification that can be audited line by line: a static bundle, two nginx configurations and no runtime secrets. It is deployed at csirt.nusantararegas.com ahead of its public announcement.