# Security notes

RDP Manager stores and transmits real credentials. Read this before deploying.

## Intended use

This is an **administration** tool for machines you own or are authorized to
manage. It authenticates to targets with **administrator credentials you
provide** and automates routine tasks (enable RDP, create local accounts, set
firewall rules). It performs no scanning, brute-forcing, exploitation, or
access to machines you don't already control. Do not use it against systems you
are not authorized to administer.

## What the tool does well

- **Login password**: salted and hashed with Werkzeug (`pbkdf2:sha256`). Never
  stored or logged in clear. No hardcoded default — a random one is generated on
  first run and must be changed/overridden.
- **Stored RDP passwords**: encrypted at rest with Fernet (AES-128-CBC + HMAC).
  The plaintext is only decrypted when you view or export it.
- **Secrets management**: the Flask session key and the Fernet encryption key
  come from environment variables, or are generated once and written to the
  gitignored `instance/` directory with `0600` permissions.
- **Transport**: WinRM over **HTTPS** (port 5986) is supported and recommended;
  set it per machine under *Advanced (WinRM transport)*.
- **Input handling**: machine names are validated to a safe character set, and
  all values interpolated into PowerShell use single-quoted, escaped strings.
  The web UI escapes all dynamic content to prevent stored XSS.
- **Session cookies**: `HttpOnly` and `SameSite=Lax`; set `SESSION_COOKIE_SECURE=1`
  when serving over HTTPS.

## Known limitations — plan around these

- **Key-vs-data locality.** The encryption key sits on the same host as the
  database. Encryption protects a *copied or leaked* database file (backups,
  exports); it does not protect against an attacker with full local access to
  the host. For stronger protection, supply `RDP_ENCRYPTION_KEY` from an
  external secret store and don't persist it to disk.
- **Plain HTTP WinRM (port 5985)** sends credentials with only NTLM-level
  protection. Prefer HTTPS WinRM in production.
- **No multi-user / RBAC / audit log.** A single shared password gates the whole
  app. Restrict network access accordingly (loopback by default; VPN/trusted
  network for shared use).
- **No rate limiting** on the login endpoint. Front it with a reverse proxy that
  provides throttling if exposed beyond localhost.
- **Dev server.** `python app.py` uses Flask's built-in server — run behind a
  production WSGI server + HTTPS reverse proxy for shared deployments.

## Hardening checklist for shared deployments

1. Set a strong `RDP_MANAGER_PASSWORD` (or change it immediately in the UI).
2. Serve over HTTPS; set `SESSION_COOKIE_SECURE=1`.
3. Provide `SECRET_KEY` and `RDP_ENCRYPTION_KEY` from your secret store.
4. Bind to loopback and reverse-proxy, or restrict to a VPN/trusted network.
5. Use HTTPS WinRM (5986) with certificate verification enabled.
6. Back up `instance/encryption.key` securely — without it, stored passwords
   cannot be decrypted.

## Reporting

If you find a security issue in this tool, do not open a public issue with
exploit details — contact the maintainer privately.
