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 areCHATSHARE_DUFS_USERNAME,CHATSHARE_DUFS_PASSWORD, andCHATSHARE_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 mode0600. - 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_tokenreturned by/_chatshare/sessionreach 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.credentialsand 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
initaccepts only127.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 to0600. putrejects 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-symlinkandallow-deleteare disabled by default. - URL imports first write a private
0600object underChatSharePaths.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/PATCHhas 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-hostvalues. Forwarded headers never establish authority; wildcard hosts and CORS are not enabled. Login/logout and cookie writes require the configured Origin andX-CSRF-Token: <session csrf_token>, rejecting null/foreign origins and cross-site Fetch Metadata. Native explicit auth clients need no CSRF header. - Login
nexttargets must be strings containing safe relative paths. Explicit malformed values are rejected before credential verification, session issuance or private relay context replacement; a missingnextfalls back to the query value or/. - Anonymous reads require a regular file inside the managed root and only
raw,download,cacheortokenquery keys.tokencannot 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,downloadorcachequery 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-datatemplate 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-downloadswithoutallow-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. servedoes 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.