diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c686a8..f7d51c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,19 @@ remain historical snapshots. Beta does not mean error-free operation. ## [Unreleased] +### Security + +- Raise the transitive `filelock` floor to 4.2.1 and pin 4.2.4 with hashes, replacing + vulnerable 3.32.5. No unrelated dependency upgrades. This source change does not + replace the existing signed Beta.5 archive or its package-manager installations. + +### Documentation + +- Document the Beta.5 mission, project, proof and local-check boundaries in the agent + guide; clarify Homebrew 7 requirements, profile ownership and update commands. +- Separate public pull-request workflows from sanitized private exports and document + the explicit OSV scan of all four shipped lockfiles. + ## [0.20.0-beta.5] — 2026-10-21 ### Security diff --git a/CLAUDE.md b/CLAUDE.md index 727689e..ce5cb31 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,13 +14,39 @@ preferences live in `USER.md`. All three are operator-owned prompt state and rel |---|---| | Gate path | `policy.py`, **993 lines** — has to stay readable in one sitting | | Tools | **35**, every one gated | -| Suites | **3355** collected tests · **269** adversarial · 44 end-to-end | +| Suites | **3356** collected tests · **269** adversarial · 44 end-to-end | | Home | · docs at `/docs/` | | Repository | `talos-kernel/talos` is the public source tree | -⚠️ **`public` is blocked for pushing.** Its push url is a deliberate dead end — the -published state is only ever produced by `scripts/sync-public.sh` into a separate clone. -A direct push from here would carry 108 commits and a real author address across. +**Check the checkout before publishing.** Contributors to the public repository use +a branch and pull request. A private development checkout must publish only a reviewed, +sanitized tree through `scripts/sync-public.sh` into a separate public clone; never push +private history. Inspect the remotes and current branch instead of assuming their names. + +## Current capabilities and installation context + +Beta.5 introduced [missions and projects](docs/missions.md), `/continue`, outcome +receipts and a loopback local-model check. Mission templates and saved project context +grant no permission: each action still passes the kernel. Mailbox missions read mail +and prepare local drafts; they do not send mail. A recorded successful action is +historical evidence, not proof that an artifact remains unchanged. Receipts omit prompts +and result bodies, but artifact paths can still need redaction before sharing. + +`talos local-check` tests a loopback endpoint without user content and refuses redirects; +it cannot prove that another process never uses the network. See the mission guide for +the exact commands and limitations. + +[Homebrew](docs/homebrew.md) requires Homebrew 7+, Apple Silicon and macOS 14+. The tap +owns the code; private state lives in `~/.talos/homebrew` (directories 0700, newly created +identity/configuration files 0600). A shared or symlinked profile is refused. Explicit +`TALOS_PROFILE_DIR` overrides must be absolute. Existing installations are not imported +automatically; do not overwrite operator state with repository templates. Homebrew +installations update through `brew upgrade talos-kernel/tap/talos`; `talos update` +refuses them. Source installations retain their own profile and update path. + +The source branch can contain fixes newer than the latest signed release. Check +`CHANGELOG.md`, the release tag and `site/status.json` before claiming a fix is shipped; +a source commit does not change an existing signed archive. ## The rule everything rests on @@ -274,7 +300,7 @@ properties covered by `test_fallback_control.py` and `test_runtime_failure_repai ```bash python3 -m venv .venv && . .venv/bin/activate && pip install --require-hashes -r requirements.lock -r requirements-dev.lock -python -m pytest tests/ -q # 3355 collected tests; platform-specific skips are explicit +python -m pytest tests/ -q # 3356 collected tests; platform-specific skips are explicit python redteam.py # 269 adversarial cases — mandatory for any kernel change python e2e.py # 44 cases against a real model (costs tokens and time) python -m talos --once # single cycle, for diagnosis @@ -287,6 +313,8 @@ python -m talos status # what the event log says it did last python -m talos health # runs, errors, schedules, last anchor — no network, exit 1 on a broken chain python -m talos report # the event log as a record a third party can read python -m talos review # what this installation should change — writes nothing +python -m talos proof --format json # recorded outcomes; inspect paths before sharing +python -m talos local-check --help # options for a loopback-only model check python -m talos ask "…" # one turn, no chat — cli: must be in the allowlist python -m talos chat # a session here; the ceiling hangs on the tty, not the command python -m talos events # what happened — read-only, filterable @@ -306,9 +334,18 @@ mock HTTP endpoints in new tests use reserved example domains, not private IP li ## Dependencies: intent vs. what gets installed -Scan the shipped pins explicitly with OSV: `osv-scanner scan source --no-resolve ---lockfile requirements.txt:requirements.lock --lockfile requirements.txt:requirements-dev.lock`. +Scan all four lockfiles explicitly with OSV: + +```sh +osv-scanner scan source --no-resolve \ + -L requirements.txt:requirements.lock \ + -L requirements.txt:requirements-dev.lock \ + -L requirements.txt:requirements-verifier.lock \ + -L requirements.txt:deploy/computer-requirements.lock +``` + Automatic discovery scans the range files and misses these nonstandard lock names. +Record the scan date and result; a previous clean scan does not cover new advisories. `requirements*.txt` is the statement of intent (ranges). `requirements*.lock` is what gets installed: every version pinned, every file hashed, resolved for every platform @@ -345,20 +382,11 @@ covers the packages only through it. `pip` is never upgraded unpinned first. that did not survive an update makes a deliberately configured install answer with the shipped default. The fallback stays, but it leaves a trace — and a real deployment names its model in `talos.env` so the fallback is *its* model, not this repo's. -9. **Two repositories, and the remotes say which is which.** In this working tree - `private` carries the full history and the real author address; `public` is - `talos-kernel/talos`, an own clean history from zero. Run `git remote -v` for the - addresses — ⚠️ they are deliberately **not** written out here, because this file is - published with the tree, and the private one has no business being in it. The - deployment target is neither: it is a running instance fed by `rsync`, and a third - remote for it no longer exists. - ⚠️ Moved into the organisation on 2026-08-06 by pushing fresh, **not** by transfer: - a transfer leaves a permanent redirect from the personal account, and with zero stars - it would have bought nothing. The old repo was deleted, so no redirect exists. - ⚠️ **`public` is blocked - for pushing** — its push url is a deliberate dead end. The public state is only ever - produced by `scripts/sync-public.sh` into a separate clone; a direct push from here - would carry the whole private history across. +9. **Private and public history stay separate.** Public contributors work on the + public tree through branches and pull requests. Private development uses the + sanitized export described above. Never merge a private branch into the public + repository or publish local machine paths, operator identities or private remotes. + A running operator installation is a separate deployment, not a Git remote. 10. **An operator installation is not this repo.** The instance on the operator's machine has its own `SOUL.md` (its first heading is the agent's *name*), its own `CLAUDE.md`, its own env file and its own `data/`. Sync the **package** (`talos/` → `talos/`), never diff --git a/README.md b/README.md index 4095c94..2906b5f 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,10 @@

- - Tests + Tests Red team Gate path Tools @@ -54,7 +54,7 @@ operation or a substitute for reviewing permissions and keeping backups. [Watch a recorded session](https://talos-agent.ch/console.html) · [Install with Pinokio](https://github.com/talos-kernel/talos-pinokio) -Apple Silicon on macOS 14+: [install the CLI with Homebrew](docs/homebrew.md). +Apple Silicon on macOS 14+ with Homebrew 7+: [install the CLI with Homebrew](docs/homebrew.md). **New to Talos?** [Try three small, checkable tasks](docs/first-task.md): turn notes into a handover, save and read back a local note, and compare release notes without inventing @@ -67,6 +67,10 @@ checks. Resume saved project context with `/continue` and inspect recorded outco with `talos proof`. Templates grant no extra permissions; external sends and protected actions retain their existing gates. +**Source versus release:** `main` can contain fixes newer than the signed installer. +The [unreleased changelog](CHANGELOG.md#unreleased) records the `filelock` security +update; the existing Beta.5 archive and Homebrew package retain their published pins. + ## Is Talos right for you? - **Run local models:** connect Ollama on hardware you control, or use a configured cloud provider. diff --git a/docs/homebrew.md b/docs/homebrew.md index 172d41d..0ba37f8 100644 --- a/docs/homebrew.md +++ b/docs/homebrew.md @@ -4,6 +4,9 @@ Talos's own tap packages the beta CLI, not a notarized desktop application or a Homebrew/core formula. Intel Macs and Linux are not supported by this formula; use the signed installer for the other supported environments. +Homebrew 7 or newer is required. Run `brew update` before installing with an older +Homebrew installation. + ```sh brew install talos-kernel/tap/talos talos setup terminal diff --git a/requirements.lock b/requirements.lock index bc011ba..b151492 100644 --- a/requirements.lock +++ b/requirements.lock @@ -413,10 +413,12 @@ ddgs==9.16.0 \ faster-whisper==1.2.1 \ --hash=sha256:79a66ad50688c0b794dd501dc340a736992a6342f7f95e5811be60b5224a26a7 # via -r requirements.txt -filelock==3.32.5 \ - --hash=sha256:142cd9fa77a872c5e78c62329a0d15278fadc686eb89e760017968961a4fd6b2 \ - --hash=sha256:f6a6a28f743f9b95ce19db5abe0f376f75eb56517dff21e1a4751e2657d3e83d - # via huggingface-hub +filelock==4.2.4 \ + --hash=sha256:301241438c57936ef93f4243a94f2559022268bfcf9b375a9a72eb0f8db8358e \ + --hash=sha256:c6d8663535e1650ee430507b4ffbac7b464dd64b7647ea0112a9f406499d163d + # via + # -r requirements.txt + # huggingface-hub flatbuffers==25.12.19 \ --hash=sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4 # via onnxruntime diff --git a/requirements.txt b/requirements.txt index 8980752..e75c6f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,4 @@ anyio>=4.14.2 # transitiv ueber httpx. Untergrenze 4.14.2: alles # GHSA-5p39-cfhj-2xmp (CVSS 6.8). Dieselbe Regel wie bei idna. certifi>=2026.10.19 # transitiv ueber requests/httpx. Untergrenze schliesst # PYSEC-2026-4320 / GHSA-6q48-6c7w-9gw2 (CVSS 9.1). +filelock>=4.2.1 # Transitive transcription-cache dependency: October locking security fixes. diff --git a/site/console.html b/site/console.html index 22d9b20..f9d77d0 100644 --- a/site/console.html +++ b/site/console.html @@ -378,7 +378,7 @@

Witness one deed from door to ledger.

This candidate, measured
- 3355automated tests + 3356automated tests 269/269adversarial 993lines · gate 35gated tools @@ -554,7 +554,7 @@

Numbers this candidate must ship.

0.20.0-beta.5
beta release
public installer v0.20.0-beta.5
-
3355
automated tests, collected by pytest
+
3356
automated tests, collected by pytest
269
adversarial cases, all behaving
993
lines in policy.py, readable in one sitting
35
tools, every one through the gate
diff --git a/site/docs/index.html b/site/docs/index.html index 4dd9b6d..90548ce 100644 --- a/site/docs/index.html +++ b/site/docs/index.html @@ -244,7 +244,7 @@

Talos AI agent: the field manual

That one decision shapes the rest of this manual. It is why the command list is short, and why a few obvious conveniences are missing on purpose.

-
3355automated tests
+
3356automated tests
269/269adversarial
993gate lines
35gated tools
diff --git a/site/index.html b/site/index.html index 2e85b01..9414066 100644 --- a/site/index.html +++ b/site/index.html @@ -638,8 +638,8 @@

The bounds are named.

Measured, with the path stated

None of this asks for belief. The installer runs the unit and adversarial suites in front of you; the real-model cases are a separate opt-in E2E run.

-

Release snapshot: 0.20.0-beta.5. Counts describe its test suite, not speed or real-world success rates.

-
0
automated tests collected from the source tree
+

Source tree based on 0.20.0-beta.5, including unreleased fixes. Counts describe the source test suite, not speed or real-world success rates; signed release contents follow their tag.

+
0
automated tests collected from the source tree
0
adversarial cases trying to pass the kernel
0
opt-in end-to-end cases against a real model
0
lines in the file that decides every verdict
diff --git a/site/llms.txt b/site/llms.txt index 3915a11..a5f89d5 100644 --- a/site/llms.txt +++ b/site/llms.txt @@ -6,7 +6,7 @@ - Permission kernel: 993 lines of Python, the only code that decides - 35 tools, all gated; unattended runs cannot escalate -- 3355 tests collected in the source tree; 269/269 red-team cases passed in source verification. Release contents follow their own signed tag. +- 3356 tests collected in the source tree; 269/269 red-team cases passed in source verification. Release contents follow their own signed tag. - MCP servers run only inside a UID-separated worker, from an operator-owned registry — no marketplace, no third-party code in the agent process - Channels: Telegram, mail (IMAP pull), CLI, WhatsApp via an operator-controlled broker — every channel fetches; no inbound port, no webhook - Updates: signed tarballs, verified before anything is unpacked; dependencies pinned and hashed, installed with --require-hashes diff --git a/site/redteam/index.html b/site/redteam/index.html index 0859d50..f14fe9c 100644 --- a/site/redteam/index.html +++ b/site/redteam/index.html @@ -224,7 +224,7 @@

269 ways to break an agent.

25attack surfaces
993kernel lines
35gated tools
-
3355automated tests
+
3356automated tests
0passes sold as safety
diff --git a/site/registry/index.html b/site/registry/index.html index b84eb8e..fcbfd74 100644 --- a/site/registry/index.html +++ b/site/registry/index.html @@ -239,7 +239,7 @@

The MCP registry

guide with the full protocol is docs/claude-worker.md. A curated starting point ships as examples/mcp-servers.json.

-
3355automated tests
+
3356automated tests
269/269adversarial
993gate lines
35gated tools
diff --git a/site/setup/index.html b/site/setup/index.html index 49625f3..048b679 100644 --- a/site/setup/index.html +++ b/site/setup/index.html @@ -163,7 +163,7 @@

This address moved.

Return to the keep
-
3355automated tests
+
3356automated tests
269/269adversarial
993gate lines
35gated tools
diff --git a/site/status.json b/site/status.json index 01fe1d3..0c95218 100644 --- a/site/status.json +++ b/site/status.json @@ -1,8 +1,9 @@ { "version": "0.20.0-beta.5", "release_state": "released", + "source_state": "unreleased_changes", "installer_version": "0.20.0-beta.5", - "tests": 3355, + "tests": 3356, "redteam_faelle": 269, "kernel_zeilen": 993, "werkzeuge": 35, diff --git a/site/vergleich/index.html b/site/vergleich/index.html index 1249a48..7ae81cf 100644 --- a/site/vergleich/index.html +++ b/site/vergleich/index.html @@ -290,7 +290,7 @@

The others can do more.

35tools here, every one gated
100+skills there · counted honestly
-
3355automated tests
+
3356automated tests
269/269adversarial cases
993gate lines
0inbound ports
diff --git a/tests/test_requirements_lock.py b/tests/test_requirements_lock.py index 2017c39..4792f3c 100644 --- a/tests/test_requirements_lock.py +++ b/tests/test_requirements_lock.py @@ -127,6 +127,18 @@ def test_pypdf_lock_includes_denial_of_service_security_fixes() -> None: for version, _ in _pins(RUNTIME[1])["pypdf"]) +def test_filelock_floor_and_lock_exclude_known_vulnerable_versions() -> None: + """The transcription cache must keep the October file-locking fixes.""" + requirement = next((r for r in _declared(RUNTIME[0]) + if _canonical(r.name) == "filelock"), None) + assert requirement is not None, "filelock needs an explicit security floor" + assert not requirement.specifier.contains(Version("3.32.5")) + assert not requirement.specifier.contains(Version("4.2.0")) + assert requirement.specifier.contains(Version("4.2.1")) + assert all(version >= Version("4.2.1") + for version, _ in _pins(RUNTIME[1])["filelock"]) + + @pytest.mark.parametrize("lock", [RUNTIME[1], DEV[1]], ids=["runtime", "dev"]) def test_the_lock_carries_no_machine_path(lock: Path) -> None: """Der Kopf zitiert die Kommandozeile — erzeugt mit relativen Pfaden, oder gar nicht."""