This page is for security reviewers who need to understand what is running inside psLens before approving its deployment. It covers four questions:

  1. What code is actually running?
  2. Can we audit it?
  3. How is it built and shipped?
  4. How are vulnerabilities found, disclosed, and fixed?

If you’re looking for the higher-level read-only / whitelist story, start with Security & Trust and come back here for the detail.


1. What’s Inside the Image

psLens is a single Go binary plus an embedded NATS server, packaged as a multi-stage Docker image distributed from ghcr.io/cedarhillsgroup/pslens. There is no separate database, message broker, or external worker process; one container is the whole application.

Runtime stack

ComponentPurpose
Go 1.26+Application language; binary statically linked
gorilla/muxHTTP routing
a-h/templServer-rendered HTML templates
Embedded NATS (nats-server/v2)In-process key-value store for sessions, alerts, report output
data-star (datastar.dev)Hypermedia / SSE for interactive UI; no SPA framework
GoldmarkMarkdown rendering for report output
Standard library crypto/aes, crypto/tlsEncryption at rest and in transit

There is no embedded browser, no third-party telemetry SDK, no analytics tracker. The full dependency list is go.mod in the source tree.

Base image

The runtime stage is debian:bookworm-slim with ca-certificates. No shell access is required for normal operation; psLens runs as PID 1.


2. Source Availability and Review

psLens is closed-source. The source tree is not published publicly.

For customers who need to review the code: Cedar Hills Group offers a read-only source review under NDA as part of the procurement process. Mechanics (on-site, screen-share, time-boxed access) are agreed during contracting. Reach out via the contact page to arrange.

This is the same model used by most enterprise PeopleSoft tooling: the binary is yours to run, the source is reviewable under contract, redistribution is not granted.


3. Build and Distribution

Build pipeline

StageWhere it runsWhat it produces
Source commitCedar Hills Group internal repoTagged release commit (semver)
CI buildGitHub Actions, GitHub-hosted runnersMulti-arch Docker image
PublishGitHub Container Registry (GHCR)Private package, tagged vMAJOR.MINOR.PATCH, vMAJOR.MINOR, latest, git SHA

The release pipeline injects the version, commit SHA, and ISO-8601 build timestamp into the binary at compile time via Go ldflags. You can read them back from any running instance via /healthz and the startup banner in container logs. Useful for confirming exactly which build a customer is running.

What we do today

What we don’t do yet (roadmap)


4. Dependency Management

Today

Gaps and roadmap

If your security policy requires SBOM artifacts as part of vendor onboarding, ask on the demo call. We can generate a CycloneDX or SPDX SBOM from a tagged build on request.


5. Vulnerability Disclosure and Patching

Reporting a vulnerability

Email security@cedarhillsgroup.com. Please include:

We commit to:

Patch SLA

Specific patch targets (business days for Critical, High, Medium) are disclosed during contracting.

When a fix ships, it goes out as a patch release in the same vMAJOR.MINOR stream you’re already pinned to. docker compose pull && docker compose up -d picks it up. Critical fixes are also announced by email to deployment contacts.

Subscribing to release notes

Release notes are published as GitHub Releases on the source repo. Deployment contacts are notified by email for any release with a security note.


6. What Reviewers Usually Ask

“Is the binary statically linked?” Yes. Go produces a static binary; no system library version drift.

“Does it phone home?” No. There is no outbound connection from a running psLens instance other than (a) to your SWS endpoint and (b) to your SMTP server if you’ve enabled magic-link auth. No telemetry, no update checks, no license-server callbacks.

“What user does it run as inside the container?” Confirm the current default with us on the demo call. Recommendation for self-hosters regardless: run with --user 1000:1000 and a read-only root filesystem; only /data needs to be writable.

“How big is the attack surface?” One HTTP listener (default port 8080 or whatever you configure), serving HTML and Server-Sent Events. No raw socket listeners, no UDP, no message-queue ingress, no plugin loader.