Skip to content

Security and Boundaries

Access matrix

Operation Current actor and credential
Install, initialize, and manage service The ChatArch user logged into the host
Local put and url The same ChatArch user; no HTTP request
Remote put, tree, and url from a new machine Dufs writer account in the active ChatEnv chatshare profile; HTTPS or loopback HTTP
Known concrete file GET/HEAD/Range Anonymous, including cross-site PNG embeds
Directory HTML/JSON, search, WebDAV enumeration, archives Gateway browser session or native Dufs Basic/Digest
Read-only listing of an explicitly shared directory and descendants Visitor holding its 256-bit bearer capability
URL jobs and directory-share management ChatLogin browser owner + CSRF, with exact-path Dufs write revalidation
HTTP/WebDAV upload A client holding the shared Dufs HTTP Auth credential
HTTP delete Disabled by default
Cleanup, expiry, and per-file revocation Not implemented

This matrix applies only through chatshare serve. Direct Dufs still has its original anonymous read permissions; do not expose a bypass route. A known file URL is not a secret or per-file capability. The gate prevents enumeration, not guessing file names or revoking individual published URLs. Existing Dufs permissions, including allow-delete: false, remain authoritative.

Credentials

  • The default ChatEnv type is chatshare; its fields are CHATSHARE_DUFS_USERNAME, CHATSHARE_DUFS_PASSWORD, and CHATSHARE_DUFS_BASE_URL.
  • The remote CLI reads those fields from the active profile or controlled process environment. It accepts an HTTPS base URL without URL credentials, query, or fragment; HTTP is loopback-only. It does not create another instance or parallel account configuration.
  • Default password variable: CHATSHARE_DUFS_PASSWORD.
  • The CLI accepts an environment-variable name, never a password-value option.
  • Dufs must read the account rule at startup, so the password exists in config.yaml; the file is written with mode 0600.
  • Gateway login uses a ChatLogin async backend to validate credentials with native Dufs CHECKAUTH using Basic over numeric loopback. Only ChatLogin's random HttpOnly, SameSite=Strict, Path=/ session cookie and the per-session csrf_token returned by /_chatshare/session reach the browser; Secure follows the configured HTTPS public URL. Ephemeral auth material stays only in a server-private relay context indexed by session digest, never in Principal/public session JSON, a second account database, or credentials on disk.
  • Every cookie-authorized request rechecks Dufs; logout, expiry and password rejection revoke the session. A password change takes effect when the unchanged Dufs process itself recognizes it. Sessions do not survive a gateway restart. Native explicit Basic/Digest is passed to Dufs for real verification without replaying Digest against a different method or URI.
  • An upstream 403 is a permission denial, not logout. A proxied 401 revokes a browser session only when that request forwarded its credentials; anonymous concrete-file/token failures do not revoke it. Existing delete prohibitions remain enforced, and the UI reports permission errors without forcing logout.
  • Gateway JS clears only chatshare.dufs.credentials and never stores new passwords in DOM/storage. Original non-gateway Dufs mode remains compatible and retains its legacy browser storage behavior; it is not a substitute for the server gate.
  • The password must never appear in argv, URLs, stdout, JSON, access logs, unit files, README examples, or test fixtures.
  • Usernames and passwords reject Dufs auth-rule delimiters and newlines to prevent rule injection.

Network

  • init accepts only 127.0.0.1, localhost, or ::1.
  • 0.0.0.0, ::, and LAN addresses are rejected.
  • This CLI does not configure TLS, Nginx, DNS, or public ingress.
  • External publication belongs to a separate deployment task with trusted Hosts, TLS, request size/rate limits, and rollback. Direct public binding is not acceptance.

Filesystem

  • ChatArch-managed directories default to mode 0700; credential and state files default to 0600.
  • put rejects absolute destinations, ., .., empty components, and root escapes.
  • Local publication uses same-filesystem temporary files and atomic replacement; existing files require explicit --overwrite. Remote publication preflights with authenticated HEAD and streams PUT, but Dufs has no proven atomic create-only write across independent writers, so the preflight is not a global concurrency guarantee.
  • Dufs allow-symlink and allow-delete are disabled by default.
  • URL imports first write a private 0600 object under ChatSharePaths.base/downloads/staging. Only after length, 20 GiB maximum, and SHA-256 checks does fd-relative same-filesystem hardlink publication create a no-overwrite destination. Parent/final symlinks are rejected. Staging and the served root must share a filesystem.

URL imports and directory capabilities

  • Every URL hop permits only HTTP/HTTPS default ports, without URL credentials, control characters, or fragments. Every DNS answer must be public. The connection is pinned to a validated IP while preserving the original Host and HTTPS SNI/certificate identity. Proxy environment is ignored, and ChatShare Cookie/Authorization is never sent to a source.
  • Full signed URLs and writer credentials exist only in memory; status and persistence contain only a safe source hostname. Restart marks unfinished jobs interrupted, removes private partials, and never silently resumes with persisted credentials.
  • A directory token is authority, not a public identifier. Its page renders only bounded Dufs directory entries: directory anchors stay under the token route and file anchors return to original URIs. Revocation does not change the existing anonymous concrete-file semantics.

Explicitly unsupported

  • Share expiry, download limits, or per-file revocation
  • Multi-user ownership and audit
  • OAuth/OIDC, persistent sessions, or server-side account ownership
  • S3/object keys, CDN, or multi-node replication
  • Remote-host registry or centralized orchestration

Any of these capabilities requires a product and state-model extension; it must not be disguised as a Dufs configuration toggle.

Gateway operation and limits

Install ChatShare[server]. Login and authorization belong to the application; Nginx or other reverse proxies only forward, without auth_basic or auth_request. chatshare serve runs in the foreground on 127.0.0.1:5001; --bind ::1, --port and repeated --allowed-host proxy.internal are available. create_app(ChatSharePaths.from_home()) is the importable ASGI factory. Server dependencies are imported only by serve/the gateway module. Existing managed state supplies the root, port and public origin; no parallel endpoint/password environment variables are introduced. Public URLs must be HTTP(S) origins without a subpath.

  • Run one process/worker. Defaults: 3,600-second absolute sessions, 256 sessions, 30 login attempts per rolling 60 seconds globally, 64 active HTTP requests, 4,096-byte login JSON, 128-character usernames and 1,024-character passwords. Login bodies time out after 10 seconds; upstream connects time out after 5 seconds and ordinary metadata/read I/O after 30 seconds. Authenticated streaming PUT/PATCH has no fixed upload deadline; waiting for the upstream response has a 120-second I/O idle timeout and a 30-second pool wait. Capacity failures are 429/503. Global rate limiting is deliberately bounded but can affect other users during abuse; the external proxy should add client-specific limits.
  • Proxy TLS must preserve the configured public Origin. Allowed Host defaults to the public hostname and loopback, plus exact --allowed-host values. Forwarded headers never establish authority; wildcard hosts and CORS are not enabled. Login/logout and cookie writes require the configured Origin and X-CSRF-Token: <session csrf_token>, rejecting null/foreign origins and cross-site Fetch Metadata. Native explicit auth clients need no CSRF header.
  • Login next targets must be strings containing safe relative paths. Explicit malformed values are rejected before credential verification, session issuance or private relay context replacement; a missing next falls back to the query value or /.
  • Anonymous reads require a regular file inside the managed root and only raw, download, cache or token query keys. token cannot grant directory authority. Invalid/ambiguous percent encodings, control characters, backslashes, traversal, repeated path separators and symlink escapes are rejected conservatively, including double-encoded paths and literal percent filenames.
  • Missing-file exception: after strict path/encoding/root validation, a GET/HEAD without explicit Authorization returns an empty, no-store 404 locally when the path does not exist, has no trailing slash, and has only raw, download or cache query keys (or no query). No Dufs request or directory data is needed, preserving upload clients' anonymous destination-existence checks. Existing directories, even dotted names without a trailing slash, root, metadata/search/archive selectors, token queries and writes remain gated. Invalid explicit authentication cannot fall back to this 404.
  • Anonymous 200/206 requires Dufs's real-file Content-Disposition. Directory replacement without that marker fails closed before any body is sent. Safe 304/404/416 responses never forward upstream bodies. File/download/upload traffic streams in 64 KiB response chunks; only authenticated Dufs management HTML is buffered, with a 2 MiB cap. Unsupported HTML contracts fail closed with 502. No automatic upstream redirect following or retries.
  • Management HTML must contain the packaged Dufs index-data template and versioned /__dufs_v<version>__/ asset contract. The gateway injects an explicit marker and rewrites assets to its packaged JS/CSS/favicon; it never mutates installed Dufs runtime assets. Only gateway-owned assets/endpoints are public exceptions, not similarly named user files.
  • All responses are no-store with Cookie/Authorization Vary. Raw file responses receive CSP sandbox allow-scripts allow-downloads without allow-same-origin, preventing uploaded active content from reading logged-in same-origin APIs. PNG embeds remain possible. This intentionally limits active-content previews. Trusted management assets are not sandboxed; management pages use a separate restrictive CSP. Gateway JS hides page snapshots on pagehide and reloads restored pages.
  • serve does not install a background service, change proxies/accounts or log credentials. Use a normal service supervisor in production and validate the target Dufs template, login/logout, upload clients, proxy/TLS, ranges/hashes and rollback before cutover. Unit tests use temporary directories and mocked upstreams; they do not replace live acceptance of the target deployment.