PRISM is an internal vulnerability management and reporting tool developed by CAT (Cyber Action Team), the internal penetration testing team at Norsk helsenett SF (NHN). It provides a centralized platform for delegating, tracking, and reporting security vulnerabilities discovered during assessments.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
PRISM consists of two main components:
- API - Backend service written in Go, providing a GraphQL and REST API
- Web - Frontend application built with SvelteKit
The easiest way to get started is using the provided DevContainer configuration with VS Code or any compatible IDE.
-
Open the project in VS Code
-
When prompted, click "Reopen in Container" (or run the command
Dev Containers: Reopen in Container) -
The container will automatically:
- Install Go, Node.js, and required dependencies
- Start mocc as a local OIDC provider on port 9999
- Install npm dependencies and start the web dev server
-
Start the API server in a terminal:
cd api CONFIG_PATH="config.yaml" go run .
-
Access the application at
http://localhost:5173
The mocc OIDC provider comes with pre-configured test users:
| Role | |
|---|---|
[email protected] |
Admin (configured in config.yaml) |
[email protected] |
Regular user |
[email protected] |
Regular user |
If not using DevContainer:
- Install Go 1.25+ and Node.js 20+
- Start a mocc instance or configure another OIDC provider
- Create
api/config.yaml(see Configuration section) - Install and run:
# Terminal 1 - API cd api CONFIG_PATH="config.yaml" go run . # Terminal 2 - Web cd web npm install npm run dev
PRISM is configured via a YAML file. The path is specified by the CONFIG_PATH environment variable.
oidc:
mocc: # Provider key (used in URL path)
name: "Mocc IdP" # Display name on login page
clientID: "prism-local-client"
clientSecret: "prism-local-secret"
redirectUri: "http://localhost:5173/api/callback"
providerUri: "http://localhost:9999"
cors:
origin: "http://localhost:5173" # Frontend URL
admins:
- [email protected] # Users with admin privileges
database:
path: "./.tmp" # SQLite database location
events:
interval: 60 # Event processing interval (seconds)
slack:
token: "" # Slack bot token (optional)
webhookUrl: "" # Slack webhook URL (optional)
secrets:
HMAC_SECRET_KEY: "change-this-in-production" # Used for signing tokensYou can configure multiple OIDC providers:
oidc:
azure:
name: "Microsoft AD"
clientID: "your-azure-client-id"
clientSecret: "your-azure-client-secret"
redirectUri: "https://prism.example.com/api/callback"
providerUri: "https://login.microsoftonline.com/your-tenant-id/v2.0"
gitlab:
name: "GitLab"
clientID: "your-gitlab-client-id"
clientSecret: "your-gitlab-client-secret"
redirectUri: "https://prism.example.com/api/callback"
providerUri: "https://gitlab.example.com"PRISM is distributed as a Helm chart via ghcr.io/norskhelsenett/prism/helm.
- Kubernetes cluster
- Helm 3+
The API configuration must be deployed as a Kubernetes Secret before installing the Helm chart:
kubectl create secret generic api-config-secret \
--from-file=config.yaml=/path/to/your/config.yaml \
-n your-namespaceExample production config.yaml:
oidc:
azure:
name: "Microsoft Entra ID"
clientID: "your-client-id"
clientSecret: "your-client-secret"
redirectUri: "https://prism.example.com/api/callback"
providerUri: "https://login.microsoftonline.com/your-tenant-id/v2.0"
cors:
origin: "https://prism.example.com"
admins:
- [email protected]
database:
path: "/data"
events:
interval: 60
slack:
token: "xoxb-your-slack-token"
webhookUrl: "https://hooks.slack.com/services/xxx/yyy/zzz"
secrets:
HMAC_SECRET_KEY: "generate-a-secure-random-string"image:
repository: ghcr.io/norskhelsenett/prism
tag: "latest"
prism:
ingress:
enabled: true
host: prism.example.com
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
tls: true
storageClassName: standard
# Resource limits (adjust based on your needs)
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "1"
# The config secret must exist before deployment
mounts:
- name: config
mountPath: /config
fromSecret: api-config-secret
readOnly: true
- name: data
mountPath: /data
storage: 10Gi
statefulSet: true
- name: tmp
inMemory: true
mountPath: /tmp
storage: 50Mihelm upgrade --install prism oci://ghcr.io/norskhelsenett/prism/helm \
-f values-override.yaml \
-n your-namespace \
--create-namespacekubectl get pods -n your-namespace
kubectl logs -f prism-0 -n your-namespacemocc (Minimal OpenID Connect Core) is a tiny, opinionated mock OIDC provider written in Go. It supports the authorization code flow, provides a JWKS endpoint, and issues short-lived ID tokens. The DevContainer automatically starts mocc on port 9999.
prism/
├── api/ # Go backend
│ ├── auth/ # OIDC authentication
│ ├── config/ # Configuration loading
│ ├── database/ # SQLite database layer
│ ├── models/ # Data models
│ ├── routes/ # HTTP handlers
│ └── main.go # Entry point
├── web/ # SvelteKit frontend
│ ├── src/
│ │ ├── lib/ # Shared components and utilities
│ │ └── routes/ # Page routes
│ └── static/ # Static assets
├── .cluster/ # Helm charts
│ └── prism/
├── .devcontainer/ # DevContainer configuration
└── .docs/ # Documentation and screenshots
Report security vulnerabilities to cat[at]nhn.no. See .well-known/security.txt for details.
This project is licensed under the MIT License. See LICENSE for details.
CAT - Cyber Action Team Norsk helsenett SF (NHN)





