Skip to content

Security: PashaCore/POps

SECURITY.md

Security Policy

Supported Versions

Currently, POps is in active development. Security updates are applied to the main branch and the latest tagged release.

Version Supported
0.1.x ✅
< 0.1 ❌

Security Architecture

POps runs as SYSTEM/Administrator on endpoints, so it is designed defensively. The current guarantees:

  1. Agent identity & authentication. A device enrolls with an expiring enrollment token (optionally bound to a lab; single-use, or limited to a set number of devices; delivered by the installer). On first connect the server issues a per-device secret; the agent stores it in a SYSTEM/Administrators-only store (C:\POpsData\secure, inheritance disabled) and presents it as X-Agent-Secret on every later connection. The secret is bound to the server-resolved hardware identity, not the URL, and can be revoked from the panel. The server stores only the SHA-256 of the secret, so a leaked database cannot be replayed to impersonate an agent — this is the deliberate reason a shared secret (rather than a client keypair / mTLS) is accepted for v1; mTLS is a roadmap hardening, not a correctness fix. For reboot-to-restore (Deep Freeze) machines an optional freeze-excluded mirror keeps the secret across reverts. Authentication runs in accept-both mode during rollout and can be enforced (enforce_agent_auth), after which unauthenticated agent connections — on /ws/agent and the agent HTTP endpoints — are rejected (WebSocket close 4401 / HTTP 401) and the rejection is written to a log agents cannot forge. The Vision tunnel (/ws/vision) accepts only the device's own secret, whatever the enforcement setting: an enrollment token is not enough, so nobody holding one can stream fake frames under another device's name. The newer agent endpoints (software inventory, Windows Update status, helpdesk tickets) accept only enrolled agents with a valid secret, even while enforcement is off, and only such agents' events can change a device's quarantine state.
  2. Transport. The agent refuses a non-TLS (http:///ws://) server address unless it is loopback; production must be https:///wss://. Credentials are never sent over an insecure transport. The agent validates the server's TLS certificate with the platform's default chain and hostname checks (there is no accept-all bypass), so a same-LAN attacker cannot present a rogue certificate for the server's hostname. For self-hosted sites that use a self-signed certificate, certificate pinning via the enrollment token (embedding the server certificate fingerprint the agent then pins) is a planned hardening.
  3. Signed updates (supply chain). Releases are signed with ed25519. The private key lives only in CI / GitHub Secrets — never on the server or on agents. Each agent has the public key compiled in and, before stopping any process or touching a file, verifies the signed manifest.json and the package's SHA-256, refuses any version not strictly newer than its own (downgrade protection), and takes the manifest only from its own server's update_agent command. It downloads the package from that server or, when the command lists them, from PCs in its own subnet (lab peer cache, docs/agent.md); a peer supplies bytes only, and any source must match the signed size and SHA-256. Rollback is itself a signed Windows Installer transaction. An admin-uploaded package is verified against its signed manifest server-side before it can be dispatched.
  4. Dashboard access. JWT in an httpOnly cookie, CSRF protection on state-changing requests, and Role-Based Access Control (superadmin / admin / viewer). User administration is restricted to superadmin. Optional per-account two-factor authentication (TOTP, RFC 6238) is available — off by default and enrolled from the settings page; when enabled, login requires an authenticator code in a second step.
  5. Endpoint hardening. Secrets are readable only by SYSTEM/Administrators (no Users:Read, so students cannot read BypassSecret); the identity file's ACL is reset on every start; the offline unlock code has attempt lockout with exponential backoff and constant-time comparison, and from 0.1.12 on is derived from a per-device key the server issues over the authenticated channel (a key read on one PC opens only that PC); the tray IPC bounds message sizes.
  6. Transparency. A POpsVision (remote screen) session asks for consent, or, for a mandatory admin session with a written reason, shows a countdown and a notice. Screen previews update the tray tooltip and notify at most every five minutes. The tray is always visible; there is no hidden/stealth mode; there is no keystroke logging.
  7. API tokens for automation. Scripts and other systems use /api/v1 with an API token instead of a person's login. A token has the viewer or admin role, never superadmin; it is shown once and only its SHA-256 hash is stored; it cannot manage users or tokens, use 2FA, or open remote screen and remote input. Only a superadmin creates and revokes tokens, and what a token does is logged under its name.
  8. Server dependencies. The backend's Python dependencies are hash-locked (Backend/requirements.lock, installed with pip install --require-hashes), so a changed file on the package index is refused before anything is installed. The CI tools are hash-locked too (.github/requirements/*.lock), the Docker base images are pinned by digest, workflow tokens are read-only unless a job needs more, and release tags are SSH-signed (keys/allowed_signers). The OpenSSF Scorecard rates these practices on every push to main.
  9. Directory and single sign-on. A superadmin can let people sign in with Active Directory/LDAP or OpenID Connect. LDAP works only over LDAPS or StartTLS with the certificate and host name verified; OIDC uses the code flow with PKCE, state and nonce, and checks the ID token's signature (asymmetric algorithms only), issuer, audience and expiry. A one-time ticket bound to the starting browser prevents login CSRF, and redirect targets come only from the configured redirect URI. Local accounts never reach the directory, the first local superadmin stays local, and a directory or OIDC identity cannot take over a local account; disabled, removed or unmapped directory accounts are refused and their sessions end. Provider secrets are encrypted at rest, never returned and not reused when the server, connection or CA changes. 2FA still applies.
  10. Organisational units. Scoped admins and API tokens see and act only on the devices of their own units (district → school). The server enforces the scope on every endpoint (Backend/pops/tenancy.py), including the REST API and the panel WebSocket; out-of-scope ids answer 404 and organisation-wide settings 403.
  11. File transfer. Each PC gets its own transfer and a one-time token (1 hour, stored as a SHA-256 hash) bound to that PC; the agent endpoints always need the device secret, and a wrong, used or expired token gets 404. Sending, fetching and downloading need an admin in a panel session (API tokens are refused). Every step is in the hash-chained audit log with metadata only, never the content, and the tray tells the PC's user. The agent writes only to the public desktop or its inbox folder and refuses shortcuts and screensavers unless the admin allowed them.
  12. Exam mode, power actions and messages. Exam mode limits a lab's network to the POps server, DNS/DHCP and an allow list, shows a banner on the PC and ends on time even offline. It is a network restriction and a notice, not proctoring: it does not watch the screen, camera or keystrokes. Power actions and messages travel as JSON fields, never through a shell; the PC's user always sees a countdown with the note, or the message itself. Messages need a person (a panel session); audit records keep only the length and the first 60 characters of a note or message.
  13. Agent capabilities. Terminal, Vision, exam mode, file transfer, power actions, messages and the lab peer cache can each be switched off on the PC (TERMINAL_ENABLED=0, VISION_ENABLED=0, EXAM_ENABLED=0, FILES_ENABLED=0, POWER_ENABLED=0, MESSAGE_ENABLED=0, PEER_CACHE_ENABLED=0); the server can only switch them off.
  14. Fuzzing. Atheris fuzz targets for the agent WebSocket handler, the request models, the signed release manifest and the notification settings run in CI. The first runs found bugs that are fixed, among them a vision_rejected message that let any connected agent end an administrator's remote-control session on another device (docs/fuzzing.md).

Threat Model

# Threat Attack Mitigation Residual risk
1 Rogue device impersonation Connect to /ws/agent/{pc} claiming to be another PC to receive its commands / send fake data Enrollment token → per-device secret; enforce_agent_auth rejects unauthenticated with 4401 While enforcement is off (rollout default), unauthenticated agents are accepted and logged; enable enforcement once the fleet is enrolled
2 Network MITM ARP-spoof a flat lab LAN to capture the secret or inject commands Agent refuses non-loopback http://; TLS (wss://) required end-to-end Operator must front the server with TLS (the agent enforces this)
3 Malicious / forged update Push a trojaned agent build ed25519-signed manifest, verify-before-execute against a compiled-in key, downgrade guard, signed rollback Compromise of the release key itself; mitigated by keeping it offline / CI-only, never on the server
4 Server / panel compromise Attacker controls the server and sends commands to agents Updates cannot be forged (signature is verified independently of the server). An agent-side capability policy can hard-disable remote terminal (execute) and/or Vision per device: the agent is the source of truth, the server can only disable, and an "enable" from the server is ignored (POST /api/system/set-capabilities + the panel's per-device controls). Biggest residual where the capability policy is not applied. Non-update commands (remote terminal execute, Vision, lockdown) are otherwise trusted from the server, so a compromised server ≈ SYSTEM code execution on every managed PC. The capability policy closes this on devices where terminal/Vision are turned off, but takes effect only on capability-aware agents (v0.1.4-alpha+); until the fleet is on that build, the panel is the crown jewel — protect it hardest.
5 Malicious local user (student) Read the bypass secret, brute-force the unlock code, tamper with identity, or crash the agent Secrets SYSTEM-only; unlock-code lockout + constant-time compare; identity ACL reset on start; bounded IPC —
6 Stolen panel credentials Reuse an admin's password / an old token after the user is removed JWT + RBAC + CSRF; optional per-account TOTP 2FA (rate-limited); JWT revocation — a token_version in the token is checked against the DB on every request, and the role is read from the DB (not trusted from the token), so deleting a user, demoting them, or changing their password invalidates their outstanding tokens immediately 2FA is opt-in (off by default) — enable it for admin accounts; no per-action re-authentication yet (planned)
7 Audit tampering Alter or delete logs to hide activity Security-relevant admin actions (remote-control session start, lockdown/unlock, bypass-code, agent-command execution with the requesting user, queue flush, releases and agent updates, enforcement, capability and scheduled-task changes, licence changes) and auth/update rejections are written to a table agents cannot write, chained with a SHA-256 hash (migration 0004, verify via /api/system/audit-verify) The chain makes tampering detectable, but the app's DB user can still UPDATE/DELETE, so it is not yet prevented — full write-prevention via a separate DB-owner role is the documented next step
8 Replay of an old signed update Re-send a genuine but outdated signed manifest Agent rejects any version ≤ installed Freshness/released_at is not enforced; the authenticated TLS dispatch channel must prevent replay
9 Covert remote control / screen watching A low-privilege or read-only panel user drives mouse/keyboard or watches a screen with no consent and no trace Remote input (execute and real mouse/keyboard) requires the admin/superadmin role and an open, reason-recorded audit session for that device; screen previews require the admin/superadmin role; live frames are delivered only to the panels of the admin who opened the session (not broadcast); the session start is written to the hash-chained audit log (metadata only — never raw keystrokes). Since v0.1.4-alpha the agent also applies remote input only during a session the tray started after the user accepted it (or after the mandatory-session notice), so a compromised server alone cannot drive the PC. Screen previews need no session; they are announced on the tray (tooltip, and a notice at most every five minutes) rather than asked for. Agents older than v0.1.4-alpha rely on the server-side check only
10 Lab peer cache abused Read or poison an update package served by a PC on the lab network Off by default; a PC listens only after the server sends "peer_cache": true with an update, on TCP 8817, for its own subnet only, for at most 2 hours, read-only (GET/HEAD of one SHA-256 name). The manifest comes only from the agent's own server, and a package from any source must match the signed size and SHA-256 When enabled, it is the one inbound port on managed PCs. Anyone on the subnet can download the (public, signed) package or try to load the port; turn it off per PC with PEER_CACHE_ENABLED=0
11 Redis compromise in multi-worker mode Write to the Redis that several backend workers share, to inject commands, frames or session grants Off unless REDIS_URL is set; docs/ha.md asks for Redis off the public network, with a password (and rediss:// for TLS) Redis is inside the trust boundary: messages on it are not signed, so write access to it is close to control of the backend. Keep it on a private network with a password
12 Directory or SSO provider compromise Take over the directory or OIDC provider, or a group mapped to superadmin Group mappings decide roles and are re-read at every sign-in; local accounts never reach the provider; 2FA still applies to panel accounts that have it The provider is trusted: whoever controls it, or a group mapped to superadmin, controls the panel. Map superadmin to a small dedicated group and use a read-only service account
13 Data left in file transfers Read files fetched from PCs on a compromised server Fetched files live in Backend/transfers (not served, not backed up), downloadable only through an admin panel session Fetched files stay on the server for 7 days (sent files until every PC has downloaded them or the token expired); fetch only what you need

If the server is fully compromised, what can an attacker do?

Honest answer: they cannot silently push a malicious agent update — every update is verified against a key the server does not hold, and downgrades are refused. They can, however, issue any command the agent currently trusts from the server on PCs where it is allowed: run PowerShell as SYSTEM (remote terminal), take screen previews, request a Vision session, lock a machine, send files to a PC or fetch files from it, put a lab into exam mode, shut PCs down or show messages, or read inventory. Remote mouse/keyboard input still needs the local session step on v0.1.4-alpha+ agents. In other words, where the terminal is enabled a compromised panel is close to SYSTEM-level remote code execution. The defense is the agent-side capability policy (since v0.1.4-alpha): a site hard-disables terminal and/or Vision per PC at install time (TERMINAL_ENABLED=0 / VISION_ENABLED=0; file transfer, exam mode, power actions, messages and the peer cache have their own …_ENABLED=0 switches), the server can only switch them off, and switching them back on needs a local administrator — so even a compromised server cannot use them there. Treat the server and panel accounts as the highest-value target.

Reporting a Vulnerability

If you discover a security vulnerability within POps, please DO NOT open a public issue.

Instead, please send an email to security@pashacore.com.tr. We will triage your report within 48 hours and work with you to understand and mitigate the issue before public disclosure.

When reporting, please include:

  • A description of the vulnerability.
  • Steps to reproduce the issue.
  • Potential impact.

Thank you for helping keep the POps platform secure!

There aren't any published security advisories