Skip to content
Security

Security posture

spane is self-hosted and built to add monitoring without adding exposure. Agents reach in over outbound-only mutual TLS, secrets live in a vault, and the platform ships hardened by default.

spane is open source (Apache-2.0) and undergoes automated (Dependabot, CodeQL, bandit, pip-audit, gitleaks) and manual pre-production review.


Trust model

How agents connect

Enrollment is the only public step, gated by a one-time token with expiry and max-uses. Everything after is mutually authenticated.

Outbound-only agents

The agent opens no inbound ports. All traffic is outbound HTTPS (443) to your spane server, so monitored hosts expose no new attack surface.

Mutual TLS

TLS 1.3 with client-cert auth and CA pinning. nginx verifies each agent certificate against the agent CA and forwards only the verified serial to the API; unverified requests are rejected at the edge.

Per-agent identity

Each agent holds a unique EC P-384 certificate issued by spane’s internal CA (OpenBao PKI), valid one year and revocable from the UI. The private key is generated on the host and never leaves it.

Secrets in a vault

Device credentials, tokens, and feed keys live in OpenBao, not the database — Postgres stores only vault path references. Nothing sensitive is logged or returned by the API.

Least-privilege agent (Linux)

  • Runs as a dedicated low-privilege user (netpulse-agent) with no login shell and no home directory.
  • Hardened systemd unit: NoNewPrivileges, ProtectSystem=strict, ProtectHome, with ReadWritePaths limited to the config directory.
  • Reads only what collectors need — /proc, /sys, /etc/os-release, and service state.

Platform hardening

Secure by default

The server side is hardened across authentication, authorization, transport, and input handling.

Password hashing

Argon2id — the memory-hard, OWASP-recommended standard — hashes new and changed passwords; older hashes upgrade transparently on next login.

Role-based access control

Deny-by-default DRF permissions enforce read/write by role, with Admin-only gates on user management and system configuration, plus full audit logging.

Authenticated WebSockets

Live alert / telemetry / topology streams validate a JWT on the WebSocket handshake and reject anonymous connections — no unauthenticated data streams.

Hardened transport

TLS-1.3-only nginx with HSTS, X-Content-Type-Options, X-Frame-Options, and Referrer-Policy; secure, SameSite, HttpOnly cookies in production.

Rate-limited auth

Login and token-refresh endpoints are throttled per real client IP behind the proxy, mitigating credential-stuffing and lockout abuse.

Input hardening

Discovery inputs are validated as strict IP/CIDR (no nmap-flag injection); CSV exports neutralize formula injection; the ORM and DSL queries avoid raw SQL.


Supply chain

Signed agent binaries

We sign released agent binaries so you can verify they came from us and were not tampered with in transit. Verify the signature before promoting a binary into production.

Public key — publishing soon
spane-agent signing keyplaceholder
# The spane agent release-signing public key will be
# published here and at the canonical URLs below.

-----BEGIN PUBLIC KEY-----
<published with the first signed release>
-----END PUBLIC KEY-----

# key id     : <tbd>
# fingerprint: <tbd>
  • This page (spane.app/security) — canonical copy
  • The GitHub repository, committed under version control
  • Attached to each signed GitHub release

How to verify (once published)

verify a downloaded binaryshell
# 1. fetch the binary + its detached signature
curl -fLO .../netpulse-agent-linux-amd64
curl -fLO .../netpulse-agent-linux-amd64.sig

# 2. verify against the published public key
openssl dgst -sha256 \
  -verify spane-agent.pub \
  -signature netpulse-agent-linux-amd64.sig \
  netpulse-agent-linux-amd64
# → Verified OK

The exact tool and command will be finalized with the signing scheme and pinned here when the key ships. The page and verification flow are in place now so nothing changes for you but the key itself.


Reporting a vulnerability

Found a security issue? Please report it privately through the GitHub repository’s security advisories rather than a public issue, and give us a reasonable window to remediate before disclosure.

Report privately