Repository navigation
Findings-catalogue fixes, part 3, and release 0.2.2 - #7
Merged
Merged
Conversation
…s on the page DEMO-01 / OWN-2 / TCD-05: the hero block was overdetermined. The record lookup alone tainted the session (every tool result is untrusted) and the scripted agent emailed the attacker whatever the page said, so the poisoned page changed nothing. - Policy: `trusted_output: true` on a tool labels its results SYSTEM rather than RETRIEVED_CONTENT, for tools whose output nobody outside can write to. Opt-in per tool; the engine exposes it and the proxy applies it. - Bundled policy v6 trusts get_customer_record (the example deployment's own records service). - The hero agent emails only where the fetched page tells it to (plain or "(at)/(dot)" addresses); a computed step may now decline to call. Tests that fail before the change: without the page the agent sends nothing; an email to an ALLOWED address is allowed without the page and refused by block-untrusted-origin after it. README, deck notes and CHANGELOG updated; the allowlist remains a second, independent reason the attacker's address is refused, and the docs say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yments included GW-13, as decided: with one SENTINEL_API_TOKEN and no admin token, that token was the operator's too. It is the credential agents hold, so agents could replace their own policy and clear their own quarantine. is_admin now accepts SENTINEL_ADMIN_TOKEN only; without it nobody administers, and check and serve say so (replacing the earlier warning). Breaking for single-token deployments that used the policy or trust-reset endpoints: set SENTINEL_ADMIN_TOKEN. The test that pinned the old behaviour is replaced by one that fails before the change. README, .env.example and CHANGELOG updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… mode GW-16: with no credential configured, SENTINEL could not tell its own dashboard from any other page the operator had open. A page anywhere could submit a form POST to a local anonymous instance (resetting trust, say), or rebind its DNS name to 127.0.0.1 and drive /mcp. AnonymousBrowserGuard (outermost middleware, anonymous mode only): - the Host must be loopback or listed in SENTINEL_ALLOWED_HOSTS (421 otherwise); a rebinding page still sends its own host name; - a POST/PUT/PATCH/DELETE whose Origin is another site, or "null", is 403; - /healthz is exempt so platform health checks keep working. Authenticated deployments are unchanged: a page cannot supply the bearer token, and the session cookie is SameSite=Strict. render.yaml lists the hosted sandbox's host; DEPLOY.md and .env.example document the setting. The attack tests fail with the guard unwired; the dashboard was checked in a browser (launch and same-origin reset work). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DEMO-07: the examples told you to run `make serve`, which requires a token, and then connected without one, so they were refused (401). connect_over_http.py and run_live_agent.py now send SENTINEL_API_TOKEN from the environment (and follow the /mcp -> /mcp/ redirect, which mcp 1.28 left to the client). A 401 gets a credential hint rather than "is the gateway running?". Checked end to end against an authenticated serve: the HTTP example's exfiltration is blocked, and the live-agent example (--offline) blocks one action and exits 0. examples/README section 6 said auth was optional, that an unset token meant no auth, and that read endpoints stay open; none of that has been true since SENTINEL started failing closed. Rewritten. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edge's own failure - EVT-1: InMemoryForensicStore stored and returned the Span objects themselves. Span is frozen, but its payload's dicts are not, so a caller holding one could rewrite stored evidence (reproduced: an argument added through a returned span appeared on the next read). It now keeps and returns deep copies. Test fails before the change. - TCD-13: the strict xfail on the teardown wedge had no raises=, so any failure in that test, a real regression included, counted as the known defect. It now expects only the wedge's pytest.fail. Locally it still xfails; the Linux CI run on this PR checks the same there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…approval - DEMO-10 / DEMO-17: the dashboard said SENTINEL tracks where "every byte" came from (lineage is per tool result) and that its log streams live (it replays the recorded steps of a run that took milliseconds). - DEMO-23: DEPLOY.md now says the Azure template's tool servers have no authentication of their own; internal-only ingress is all that keeps other workloads in the environment away from them. - DCC-06: the README says catalogue approval is trust on first use, and to review the catalogue with sentinel check before going live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DEMO-19: - build_live_model's docstring described OPENAI_BASE_URL as a separate, lower-priority case; it is one branch with OPENAI_API_KEY, and the key is sent to whatever the base URL names. The docstring and .env.example now say so, with a warning not to pair a real OpenAI key with another URL. - Azure OpenAI settings, often there only for the classifier, switched every demo run to a live model with no way back. SENTINEL_AGENT_DRIVER (auto | scripted | llm) chooses; llm fails rather than fake a model. Test fails before the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Version 0.2.2 with the findings-catalogue fixes merged in #3, #5 and #6 and those in this branch. The CHANGELOG [0.2.2] section opens with an upgrade note pointing at the breaking changes. README: PyPI now serves 0.2.1, so the install line is pip install "sentinel-prox>=0.2.2" again, with 0.1.x called out as insecure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TRUST-1: the transition model kept one last tool per (tenant, agent). Two sessions of the same principal interleaved their calls through it, making transitions neither session took (send_email->web_fetch across traces), which the model scored as anomalies. It now keeps the last tool per trace (the 64 most recent per agent). Test fails before the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last batch of findings-catalogue fixes, plus the 0.2.2 version bump. Each fix has a test that fails on the code before it, checked by running it against the old code.
Changes
trusted_output: truefor tools whose output nobody outside can write to. The bundled policy (v6) sets it onget_customer_record.block-untrusted-originafter it.SENTINEL_ADMIN_TOKENcan administer, including in single-token deployments. Breaking: a single-token deployment that used the policy or trust-reset endpoints must now setSENTINEL_ADMIN_TOKEN.SENTINEL_ALLOWED_HOSTS, and refuses state-changing requests from another site'sOrigin. This blocks DNS rebinding and cross-site forms.render.yamllists the hosted sandbox's host. Checked in a browser: the dashboard still works.SENTINEL_API_TOKENand follow the/mcpredirect. Checked end to end against an authenticatedserve. The examples README's auth section was rewritten; it described auth as optional.raises=pytest.fail.Exception, so only the hang's own failure counts. This PR's Linux CI is the check that it fails the same way there.SENTINEL_AGENT_DRIVERsetting (auto,scriptedorllm), and a correct live-model docstring.[0.2.2]gets an upgrade note, and the README install line points atsentinel-prox>=0.2.2.Testing
Windows, Python 3.11: 670 passed, 12 skipped, 1 xfailed. ruff and
mypy --strictare clean, and the wheel builds as 0.2.2.After merge
Tag
v0.2.2on the merge commit. The release run then waits for approval in thepypienvironment.🤖 Generated with Claude Code