Security

Self-audit against OWASP ASVS

The server side of GameAP has been audited against the OWASP Application Security Verification Standard (ASVS), an open list of specific, verifiable security requirements, from how passwords are stored to how uploaded files are handled.

AI agents went through the requirements one by one, and every conclusion was then checked by hand. Each requirement is marked as met, partially met or not met, with references to the code and tests behind it. Both reports are public, including the requirements that are not met yet.

How the panel is protected

Sign-in and passwords

  • Passwords are stored only as a slow one-way hash (bcrypt), never in readable form.
  • A password needs at least 12 characters, and about 46,000 common passwords are rejected.
  • After 5 wrong attempts for one account, or 20 from one IP address, sign-in pauses for 15 minutes.
  • The sign-in form gives the same answer, in the same time, whether or not the account exists.
  • A CAPTCHA can be added to the form: reCAPTCHA or Cloudflare Turnstile.

Two-factor authentication

  • Codes from an authenticator app (TOTP), plus 10 one-time recovery codes.
  • Mandatory for administrators: after a 30-day grace period, an administrator without 2FA can only set it up.
  • The 2FA secret is encrypted in the database (AES-256-GCM), and recovery codes are stored only as hashes.
  • A used code is rejected, and each sign-in allows 5 attempts. Turning 2FA off requires both the password and a code.

Sessions and API tokens

  • Session tokens are encrypted and tamper-proof (PASETO v4). They expire after 24 hours, or after 7 days with “Remember Me”.
  • Signing out revokes the token on the server. After a password change, sessions and API tokens issued before it stop working.
  • API tokens have limited scopes, are shown only once, are stored as a hash and can be revoked at any time.
  • Long-lived tokens are never accepted in links. Downloads and the live console use single-use tokens valid for at most 10 seconds.
  • Requests are authorized with a header rather than a cookie, which protects against cross-site request forgery (CSRF).

Permissions

  • Separate permissions for each action on a server: start, stop, console, files, RCON and more.
  • Anything not explicitly allowed is denied, and permissions are checked on the server for every request.
  • Users see only the servers assigned to them. For anyone else, the panel answers as if the server didn't exist.
  • Admin functions are available only to administrators. An API token reaches them only with an explicitly granted admin scope.

HTTPS and browser protection

  • A built-in Let's Encrypt client obtains HTTPS certificates and renews them automatically.
  • Only TLS 1.2 or newer, with modern ciphers that provide forward secrecy.
  • A strict Content Security Policy (CSP) blocks scripts injected into the page, which makes cross-site scripting (XSS) much harder.
  • Protection against clickjacking, content sniffing and referrer leaks, plus HSTS over HTTPS. Responses with account data are never cached.

File manager

  • File access is a separate permission for each server and is limited to that server's folder.
  • Paths with ../ and similar tricks are rejected. On the machine itself, GameAP Daemon also keeps every file operation inside its working directory (Go os.Root).
  • Archive extraction blocks files and links that would end up outside the target folder (zip slip) and limits the total size and number of files.
  • Files open in the browser inside a sandbox or are downloaded, so an uploaded HTML or SVG file can't run scripts in the panel.

Game servers and console

  • Values from server settings go into the start command as separate arguments, so they can't inject extra commands.
  • Each game server can run under its own system user, or in its own Docker or Podman container with memory and CPU limits.
  • Only administrators can change a server's start command, folder and system user.
  • Viewing the console and sending commands are separate permissions, checked for every message. The RCON password is hidden in console output.

Dedicated servers and GameAP Daemon

  • GameAP Daemon opens no network ports on the machine: it connects to the panel itself.
  • The connection is encrypted with TLS by default. After setup, the daemon trusts only the panel's own certificate authority.
  • A machine is connected with a single-use setup key that expires after an hour by default.
  • Each machine gets its own random key. The panel stores only its hash and never shows it. Mutual TLS can be required as well.

Plugins

  • Plugins run in a WebAssembly sandbox with no direct access to files, the network or environment variables, only to the interfaces the panel provides.
  • Each plugin has limits on memory, execution time and request rate.
  • Only administrators can install plugins, and packages from the catalog are checked against a SHA-256 hash.
  • HTTP requests from plugins are HTTPS-only by default and can't reach local networks or cloud metadata services (SSRF protection).

Audit log and data

  • A security audit log records sign-ins and failed attempts, denied access, changes to users, roles and tokens, file operations and plugin management.
  • Each record includes the user, IP address, time and request ID.
  • Two-factor secrets and plugin secrets are stored encrypted (AES-256-GCM).
  • All database queries are parameterized, which protects against SQL injection.
  • Server errors return a generic message; the details go only to the server log.

Security in development

Security tests

A dedicated test suite, grouped by the OWASP API Security Top 10, checks that users can't reach other people's servers, bypass sign-in or raise their own permissions. It runs on every change.

Static analysis

Every change goes through a code analyzer with security rules (gosec), and tests run against real MySQL, PostgreSQL and Redis.

Fuzz testing

Every week, sign-in, permission checks and file path handling are fed large amounts of random and malformed input.

Dependency checks

Dependencies are checked against the Go vulnerability database (govulncheck) every week and on every change to the main branch. Their versions are pinned with checksums.

Mutation testing

Every week, small deliberate bugs are planted in authentication and permission code to make sure the tests catch them.

Open source

The code is open on GitHub under the MIT license. Releases come with SHA-256 checksums, and the Docker image runs as a non-root user.

Recommendations for administrators

  1. 1

    Turn on HTTPS

    gameapctl can obtain a Let's Encrypt certificate, which the panel then renews on its own. Redirect plain HTTP to HTTPS as well.

    TLS_FORCE_HTTPS=true
  2. 2

    Turn on two-factor authentication now

    Administrators get 30 days to set it up, but there's no reason to wait. Ask other users to turn it on too.

  3. 3

    Add a CAPTCHA to the sign-in form

    This matters most when the panel is open to the internet.

    CAPTCHA_PROVIDER
  4. 4

    Require certificates from daemons

    With mutual TLS, the panel accepts connections only from daemons that hold a certificate it issued.

    GRPC_REQUIRE_MTLS=true
  5. 5

    Don't run game servers as root

    Use a separate system user for game servers, or run them in Docker or Podman containers.

  6. 6

    Install plugins only from trusted sources

    Turn on permission enforcement as well, so each plugin gets only the access it declares.

    PLUGINS_PERMISSIONS_ENFORCE=true
  7. 7

    Use your own secret keys

    gameapctl generates them during installation. With Docker or a manual installation, set long random values yourself.

    ENCRYPTION_KEYAUTH_SECRET
  8. 8

    Stay up to date

    Security fixes ship in regular releases. Watch the GameAP repository on GitHub to get notified about security advisories.

Reporting a vulnerability

Please don't post vulnerabilities in public issues. Report them privately on GitHub or by email. Reporters are credited in the release notes and the advisory.

72 hours
to acknowledge a report
14 days
for the initial assessment
14 days
to fix a critical vulnerability
90 days
until public disclosure, agreed with the reporter