Skip to content

Commit 4cc48ff

Browse files
committed
chore(release): v1.14.0 — security audit response
1 parent 150970d commit 4cc48ff

20 files changed

Lines changed: 120 additions & 56 deletions

File tree

CHANGELOG.md

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
### Removed
11-
- Composio MCP integration and SymbiBot autonomous-posting feature removed for security reasons (see SECURITY_AUDIT.md C3)
10+
## [1.14.0] - 2026-05-18
1211

13-
### Security
14-
- `DefaultPolicyGate::new()` is now fail-closed: every `ToolCall` and `Delegate` action is denied with an explicit reason unless an OPA-backed gate is wired or the operator opts into the dev-only permissive mode via `--insecure-allow-all` (or `SYMBI_INSECURE_ALLOW_ALL=1`). The previous fail-open behaviour silently allowed every action. (SECURITY_AUDIT.md C2/M3)
15-
- `DefaultPolicyGate::permissive()` was renamed to `DefaultPolicyGate::permissive_for_dev_only()` and marked `#[doc(hidden)]`; it now emits a `tracing::warn!` on every evaluated action so insecure permissive mode is visible in production logs.
16-
- `symbi up` and `symbi run` now default to the fail-closed gate; the dev-only permissive gate must be explicitly enabled.
17-
- Tool-call arguments produced by the LLM are now validated against the declared JSON Schema before the policy gate runs. Arguments that are not a JSON object — or that fail schema validation — are rejected as `LoopDecision::Deny`. (SECURITY_AUDIT.md M4)
12+
**Security audit response release.** Implements every finding in `SECURITY_AUDIT.md` (5 CRITICAL, 7 HIGH, 10 MEDIUM, 9 LOW). Out-of-band operator items live in `SECURITY-OPS.md`.
13+
14+
### Removed (BREAKING)
15+
- **Composio MCP integration + SymbiBot autonomous-posting feature** removed entirely (SECURITY_AUDIT.md C3). Affected surface: the `composio` Cargo feature flag, `ComposioToolExecutor`, the `crates/runtime/src/integrations/composio` module, the `symbiont_mcp add` / `symbiont_mcp list` CLI subcommands, the `crates/runtime/examples/composio_smoke_test.rs` example, and the `tools/fuzz/fuzz_targets/sse_jsonrpc_parsing.rs` fuzz target. Env vars `COMPOSIO_API_KEY` and `COMPOSIO_MCP_URL` are no longer read. Bring your own `ActionExecutor` for external tool dispatch — Composio dispatched LLM-supplied tool names without a static allowlist or TLS pinning.
16+
- **`SYMBIONT_ALLOW_NO_JWT_AUDIENCE` env-var escape hatch** removed (SECURITY_AUDIT.md M2). Every JWT verifier now requires an explicit `aud` configuration unconditionally.
17+
18+
### Changed (BREAKING)
19+
- **`symbi up` / `symbi run` default policy gate is now fail-closed** (SECURITY_AUDIT.md C2 / M3). `DefaultPolicyGate::new()` returns `LoopDecision::Deny` for every `ToolCall` and `Delegate` action with an explicit reason; `Respond` actions remain allowed. The previous binary hard-coded `DefaultPolicyGate::permissive()`, which silently allowed every tool call and delegation. Wire `CedarPolicyGate` / `OpaPolicyGateBridge` / your own `ReasoningPolicyGate` impl, or opt into the dev-only permissive mode via `--insecure-allow-all` (or `SYMBI_INSECURE_ALLOW_ALL=1`) with a loud stderr banner.
20+
- **`DefaultPolicyGate::permissive()` renamed to `DefaultPolicyGate::permissive_for_dev_only()`** and marked `#[doc(hidden)]`. It now emits a `tracing::warn!` on every evaluated action so insecure permissive mode is visible in production logs.
21+
- **`bundled docker-compose.test.yml` now requires `SYMBIONT_API_TOKEN`** (no `testtoken123` default) and binds published ports to `127.0.0.1` rather than `0.0.0.0` (SECURITY_AUDIT.md C5). `VM_HOST` is also required; `.env.example` is included.
22+
- **JWT verifier algorithm allowlist** (SECURITY_AUDIT.md C4). ES256 and EdDSA only for the asymmetric `Authorization: Bearer` path; HS256 only for the HMAC webhook-signature path. `RS256`/`RS384`/`RS512`/`PS256`/`PS384`/`PS512` and `none` are rejected at both the header-inspection guard and the `Validation::algorithms` allowlist. Neutralizes RUSTSEC-2023-0071 (`rsa` Marvin Attack reachable through `jsonwebtoken`) on every path operators control. The Microsoft Teams adapter (`crates/channel-adapter/src/adapters/teams/auth.rs`) still uses RS256 because the Bot Framework protocol requires it; that surface is bounded to MS-signed tokens.
23+
- **`symbi-invis-strip` 0.3.0**: forbidden range expanded with U+00AD (soft hyphen), U+0300..=U+036F (combining diacritical marks), and U+2070..=U+209F (superscript/subscript forms); `detect_injection_patterns` now NFKC-normalises input (closes fullwidth and math-alphanumeric homoglyph bypasses), adds a compact-projection scan (catches post-strip word concatenation), and flags Latin+Cyrillic mixing with a synthetic `mixed-script` marker. New `unicode-normalization` dependency. 7 new `bypass_proofs` regression tests cover each bypass class. (SECURITY_AUDIT.md H5)
24+
25+
### Added
26+
- **`SYMBI_REJECT_LEGACY_API_KEYS=1` env var**: short-circuits the deprecated O(n) Argon2 scan for unprefixed API keys (returns `None` with a warn log). Operators should re-issue every key in `keyid.secret` format. The legacy path will be removed in the next minor release. (SECURITY_AUDIT.md M6)
27+
- **`SYMBI_UNSAFE_NATIVE_SANDBOX=1` env var**: required (in addition to `SYMBI_ENV` not being `production`) to construct the `native` sandbox runner at runtime. The `native-sandbox` Cargo feature now also fails to compile in release builds via a top-of-module `compile_error!`. (SECURITY_AUDIT.md H4)
28+
- **Tool-call argument validation against the declared JSON Schema** (SECURITY_AUDIT.md M4). Arguments produced by the LLM are validated before the policy gate runs; non-object arguments and schema-violating arguments are rejected as `LoopDecision::Deny`.
29+
- **`Secret` has a hand-written `Serialize` impl that emits `"value": "[REDACTED]"`** (SECURITY_AUDIT.md M7). Derived `Deserialize` retained. Regression test asserts the JSON output never leaks the plaintext.
30+
- **`symbi-approval-relay` 0.1.1**: Slack timestamp delta widened to `i128` + `saturating_sub` to mirror the channel-adapter pattern. (SECURITY_AUDIT.md L4)
31+
32+
### Fixed
33+
- **Scheduler shell-injection sink** (SECURITY_AUDIT.md C1). `scheduler/task_manager.rs` no longer interpolates `task.config.dsl_source` into `sh -c`. The DSL is written to disk and passed via `$1` argv with a quoted-literal script.
34+
- **Toolclad `session.startup_command` shell-injection** (SECURITY_AUDIT.md H1). Parsed via `shlex::split` and executed as argv; empty / metacharacter-bearing tokens rejected.
35+
- **Firecracker host `/tmp` working directory** (SECURITY_AUDIT.md H3). Production path now uses per-uid `/run/symbi/agent_<id>` (0700) with `<temp>/symbi-<uid>/agent_<id>` fallback. Avoids cross-user `/tmp` races.
36+
- **Docker sandbox `-e KEY=VALUE` env smuggling** (SECURITY_AUDIT.md M5). Environment is now written to a 0600 tempfile and passed via `--env-file`. Env keys containing `=`, newlines, or NULs are rejected.
37+
- **HTTP-input CORS wildcard `"*"` accepted at startup** (SECURITY_AUDIT.md M1). Server now returns a `RuntimeError::Configuration` and refuses to start when the wildcard is configured.
38+
- **HTTP-input error response logging** (SECURITY_AUDIT.md L1). Replaced `tracing::debug!` of the full `Display` string with `tracing::info!` of a stable enum-tag (`Configuration`, `Security`, etc.) plus the public message. No more internal path leaks.
39+
- **Empty `ApiKeyStore` silent legacy fallback** (SECURITY_AUDIT.md L3). When a key store is configured but contains no records, a one-shot `tracing::error!` fires before falling back to the legacy env-var auth.
40+
- **`approval-relay` Slack timestamp `i64::abs` overflow** (SECURITY_AUDIT.md L4). Widened to `i128 + saturating_sub`.
41+
- **`Dockerfile` base images pinned by `@sha256:` digest** (SECURITY_AUDIT.md L6). `rust:1.88-slim-bookworm@sha256:38bc5a86…`, `debian:bookworm-slim@sha256:67b30a61…`.
42+
- **`Dockerfile` HEALTHCHECK probes the HTTP server** (SECURITY_AUDIT.md L7). `curl -fsS http://127.0.0.1:8080/api/v1/health` with the original `/proc/net/tcp` socket-listen check as a fallback for HTTP-Input-only deploys.
43+
- **All third-party GitHub Actions SHA-pinned** (SECURITY_AUDIT.md H6). Every `uses:` line carries a 40-char commit SHA with a trailing version comment. `cargo install cargo-fuzz` pinned to `0.13.1 --locked`. PR-only jobs now run with `permissions: contents: read` only (SECURITY_AUDIT.md M9).
44+
- **`deny.toml`**: stale ignores `RUSTSEC-2026-0097` and `RUSTSEC-2026-0002` removed; `RUSTSEC-2023-0071` (`rsa` Marvin Attack) documented as a runtime-mitigated ignore pointing at the JWT verifier allowlist (SECURITY_AUDIT.md M8).
45+
- **`config.rs` weak-token guard extended** (SECURITY_AUDIT.md C5 belt-and-braces). Rejects `testtoken123` literally and any token starting with `test` (case-insensitive) shorter than 20 chars. Prevents re-introduction of the historical compose default.
46+
47+
### Migration notes
48+
- **No replacement for Composio.** Implement your own `ActionExecutor` for external tool dispatch. If you were using `ComposioToolExecutor` directly, see the v1.7.0 phase guidance in `ROADMAP.md` for the `ActionExecutor` trait surface.
49+
- **If `symbi up` / `symbi run` denies every tool call after upgrade**, that is expected: wire a real policy backend (`CedarPolicyGate`, `OpaPolicyGateBridge`, or a custom `ReasoningPolicyGate`), or opt into permissive mode for local development via `--insecure-allow-all` / `SYMBI_INSECURE_ALLOW_ALL=1`.
50+
- **Operators who issued API keys before the `keyid.secret` format** should re-issue all keys in the new format and set `SYMBI_REJECT_LEGACY_API_KEYS=1`. The legacy O(n) scan path will be removed in the next minor release.
51+
- **JWT verifier**: tokens without `aud` are rejected unconditionally; remove `SYMBIONT_ALLOW_NO_JWT_AUDIENCE` from any environment file. RSA-signed JWTs are refused on every path under operator control.
52+
- **`docker-compose.test.yml`** now requires explicit `SYMBIONT_API_TOKEN` and `VM_HOST` env vars and binds to `127.0.0.1`. See `.env.example`.
53+
- **`native-sandbox` Cargo feature** fails to compile in release builds. The feature is intended only for local debugging — use the `docker`, `gvisor`, `firecracker`, or `e2b` runners in CI / staging / production.
54+
55+
### Crate versions
56+
| Crate | Version |
57+
|-------|---------|
58+
| `symbi` | 1.14.0 |
59+
| `symbi-runtime` | 1.14.0 |
60+
| `symbi-dsl` | 1.14.0 |
61+
| `repl-core` | 1.14.0 |
62+
| `repl-cli` | 1.14.0 |
63+
| `repl-proto` | 1.14.0 |
64+
| `repl-lsp` | 1.14.0 |
65+
| `symbi-shell` | 1.14.0 |
66+
| `symbi-invis-strip` | 0.3.0 |
67+
| `symbi-approval-relay` | 0.1.1 |
68+
| `symbi-channel-adapter` | 0.1.3 (unchanged) |
1869

1970
## [1.13.0] - 2026-05-07
2071

Cargo.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "symbi"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "AI-native agent framework for building autonomous, policy-aware agents that can safely collaborate with humans, other agents, and large language models"
@@ -46,11 +46,11 @@ rust-version = "1.82"
4646
clap = { version = "4.0", features = ["derive"] }
4747
tokio = { version = "1.0", features = ["full"] }
4848
sysinfo = "0.30.13"
49-
symbi-runtime = { path = "crates/runtime", version = "1.13.0", features = ["http-input", "http-api", "cloud-llm", "vector-lancedb", "vector-qdrant"] }
49+
symbi-runtime = { path = "crates/runtime", version = "1.14.0", features = ["http-input", "http-api", "cloud-llm", "vector-lancedb", "vector-qdrant"] }
5050
cron = { version = "0.15", optional = true }
5151
chrono = { version = "0.4", features = ["serde"], optional = true }
5252
chrono-tz = { version = "0.10", optional = true }
53-
dsl = { path = "crates/dsl", version = "1.13.0", package = "symbi-dsl" }
53+
dsl = { path = "crates/dsl", version = "1.14.0", package = "symbi-dsl" }
5454
symbi-channel-adapter = { path = "crates/channel-adapter", version = "0.1.3", features = ["teams", "mattermost"] }
5555
async-trait = "0.1"
5656
reqwest = { version = "0.12", features = ["json"] }

SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: symbiont
33
title: Symbiont
44
description: AI-native agent runtime with typestate-enforced ORGA reasoning loop, Cedar policy authorization, CommunicationPolicyGate for inter-agent governance, ToolClad declarative tool contracts, knowledge bridge, zero-trust security, multi-tier sandboxing, webhook verification, markdown memory, skill scanning, metrics, scheduling, symbi init/run/up/shell/repl CLI, interactive TUI (Beta), cross-instance agent messaging, human approval relay, and a declarative DSL
5-
version: 1.13.0
5+
version: 1.14.0
66
---
77

88
# Symbiont Agent Development Skills Guide

crates/approval-relay/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "symbi-approval-relay"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2021"
55
description = "Dual-channel (CLI + Slack) human approval relay for AI agent gates"
66
license = "Apache-2.0"

crates/dsl/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "symbi-dsl"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "Symbi DSL - AI-native programming language with Tree-sitter integration"

crates/repl-cli/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "repl-cli"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "Command-line REPL interface for the Symbi platform"
@@ -16,6 +16,6 @@ serde = { version = "1.0", features = ["derive"] }
1616
serde_json = "1.0"
1717
tokio = { version = "1.0", features = ["full"] }
1818
chrono = { version = "0.4", features = ["serde"] }
19-
repl-core = { path = "../repl-core", version = "1.13.0" }
20-
repl-proto = { path = "../repl-proto", version = "1.13.0" }
21-
symbi-runtime = { path = "../runtime", version = "1.13.0", features = ["http-input", "cloud-llm"] }
19+
repl-core = { path = "../repl-core", version = "1.14.0" }
20+
repl-proto = { path = "../repl-proto", version = "1.14.0" }
21+
symbi-runtime = { path = "../runtime", version = "1.14.0", features = ["http-input", "cloud-llm"] }

crates/repl-core/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "repl-core"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "Core REPL engine for the Symbi platform"
@@ -25,5 +25,5 @@ tokio = { version = "1.0", features = ["sync"] }
2525
tracing = "0.1"
2626
futures = "0.3"
2727
bytes = "1.0"
28-
symbi-runtime = { path = "../runtime", version = "1.13.0", features = ["http-input"] }
28+
symbi-runtime = { path = "../runtime", version = "1.14.0", features = ["http-input"] }
2929

crates/repl-lsp/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "repl-lsp"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "Language Server Protocol implementation for the Symbi platform"
@@ -17,4 +17,4 @@ path = "src/main.rs"
1717
[dependencies]
1818
tokio = { version = "1", features = ["full"] }
1919
tower-lsp = "0.20"
20-
repl-core = { path = "../repl-core", version = "1.13.0" }
20+
repl-core = { path = "../repl-core", version = "1.14.0" }

crates/repl-proto/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "repl-proto"
3-
version = "1.13.0"
3+
version = "1.14.0"
44
edition = "2021"
55
authors = ["Jascha Wanger / ThirdKey.ai"]
66
description = "JSON-RPC wire protocol types for the Symbi platform"

0 commit comments

Comments
 (0)