Ctrl K
ComunidadGuías…

SECURITY.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Security Policy

## Supported versions

Security fixes go to `main`. There are no backports to older tags until there is a tagged release.

| Version | Supported |
| --- | --- |
| `main` | yes |
| Anything else | no |

## Reporting a vulnerability

**Do not open a public issue.**

Use GitHub's private vulnerability reporting: [Security tab → Report a vulnerability](https://github.com/KN990x/Glassys/security/advisories/new).

Include:

- Affected commit or version
- What an attacker gains, and what access they need to start
- Steps to reproduce against a local install
- Config that matters, with placeholders instead of real keys, passwords, or hostnames

This is a hobby project. Expect a few days for a first reply. A fix ships on `main` (and in a tagged release when those exist), with credit unless you prefer to stay anonymous.

## Scope

Glassys is a **single-operator, self-hosted** gateway. These are design decisions, not vulnerabilities:

- **One operator account.** Created in the setup wizard (scrypt hash in `$GLASSYS_DATA_DIR/secrets.json`, mode `0600`). There are no roles.
- **The setup wizard is reachable until it is completed.** Whoever can hit the bind first claims the instance. Complete setup immediately. Do not publish the port before that. A report that the wizard can be re-run after a password exists *is* in scope.
- **No password recovery.** Deleting the operator hash from `secrets.json` (or the data volume) reopens setup. That already requires filesystem access to the host.
- **Operator auth is always on**, including behind Cloudflare Access or another identity proxy. Edge auth is extra, not a replacement.
- **`edgeAuth: header` is only as strong as the proxy in front.** If the proxy does not strip the identity header, a client can send it. Misconfiguration of that mode is a deployment issue; a report that Glassys accepts the header when the proxy failed to strip it *is* in scope only if Glassys is what failed to document the requirement.
- **Plain HTTP on localhost is the default.** `Secure` cookies follow `x-forwarded-proto` / `publicUrl` when you terminate TLS. Exposing `0.0.0.0` without TLS is a deployment choice.
- **Auto-run plus a host workspace is operator access to that machine.** Sandbox / auto-run toggles are visible in Settings when the adapter supports them. Cursor’s headless SDK cannot pause for a human OK; auto-run off uses Auto-review (deny), not a prompt. ACP with auto-run off denies file writes and terminal create.
- **The JWT in `sessionStorage` is reachable to XSS in the PWA.** Treat XSS in `web/` as in scope. Do not treat “the token is also in sessionStorage” by itself as a finding.
- **`GET /api/auth/status` and `GET /health` are unauthenticated** (whether setup is done; name/version/protocol). That is intentional.

Reports that require the operator password, adapter API keys, or a shell on the host are out of scope.

## Deployment reminders

- Never commit `.env`, `secrets.json`, or `$GLASSYS_DATA_DIR`.
- Prefer Cursor SDK login (`~/.cursor/sdk/auth.json`) or the adapter’s API key. Cursor IDE / cursor-cli login is a different store.
- Default bind is `127.0.0.1`. Binding `0.0.0.0` is explicit in `config.yaml` / `GLASSYS_BIND`.
- Put a TLS reverse proxy in front if the PWA is reachable off the LAN. Keep WebSocket idle timeouts high (`/ws`); agent runs last minutes.
- Rotate the operator password from Settings. That bumps `jwtEpoch` and signs other sessions out.