Skip to content

fix(triage-agent): serve only localhost unless unauthenticated access is allowed - #346

Merged
JackYPCOnline merged 5 commits into
mainfrom
fix/triage-agent-session-auth
Nov 10, 2026
Merged

JackYPCOnline merged 5 commits into
mainfrom
fix/triage-agent-session-auth

Conversation

@JackYPCOnline

@JackYPCOnline JackYPCOnline commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

The triage-agent backend kept every conversation in one process-wide dict keyed by a client-supplied session_id, and handed those IDs out three ways: GET /sessions listed them, GET /agents/status listed them again, and GET /mcp/logs (polled by the frontend, forwarded by CloudFront) returned log entries carrying each full session_id and the first 50 characters of each user message. With an ID, anyone could read (GET /sessions/{session_id}/history) or delete that session. The IDs were short client-generated strings, and /chat fell back to a shared "default" session.

Every session now has a random UUID, and nothing returns one to anyone but the session's own client, so a caller can only reach sessions whose ID they already hold. The sample still has no user authentication; the README now says so plainly and points to adding it before real use.

Public API changes

  • GET /sessions and GET /agents/status are removed. The frontend called neither.
  • session_id must be a UUID; anything else gets a 400. The frontend now generates one with crypto.randomUUID() and replaces a stored old-format ID.
  • GET /mcp/logs entries shorten session IDs to their first 8 characters and no longer include user message text. This is enforced inside add_server_log, so it covers every call site.
  • The backend, start.sh and the frontend dev server bind 127.0.0.1 by default (HOST/PORT override). The stack sets HOST=0.0.0.0 and PORT=80 instead of sed-patching main.py.

Template hardening: port 80 accepts only CloudFront's origin-facing prefix list (looked up by a small custom resource, since its ID differs per region), the SSH rule is gone (SSM was already attached), and the instance role drops s3:* on * and AmazonBedrockFullAccess for bedrock:InvokeModel* and s3:GetObject on the app package.

numpy and pandas are dropped from requirements.txt. Nothing imports them, and their pins need Python 3.11+, so on the template's Ubuntu 22.04 (Python 3.10) pip install failed and the backend never started.

Breaking changes

  • Existing sessions with old-format IDs are not reachable; the frontend starts a new UUID session on load.
  • No more SSH to the instance; use SSM Session Manager.
  • The backend is no longer reachable directly on the instance's public IP, only through CloudFront.

Testing

  • Deployed the stack with deploy.sh to a personal account (us-west-2), then deleted it. Through CloudFront: chat streamed from Claude Sonnet 4.6 using the narrowed instance role, /mcp/logs held neither the session's UUID nor the user's text, and no UUID could be harvested. GET /sessions and GET /agents/status return 404 on the instance. Port 80 on the instance's public IP timed out and port 22 was closed.
  • The same live check against the previous commit reproduced the leak: /mcp/logs gave up the victim's UUID and name, and the harvested UUID read and deleted the session.
  • On main, a local run lists the session, returns its messages, and deletes it with no credential.
  • cfn-lint on the template: no new findings.

This PR was drafted by an AI coding agent on behalf of the account owner, who reviews it before it leaves draft.

@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Latest scan for commit: e125ece | Updated: 2026-11-09 19:48:38 UTC

✅ Security Scan Report (PR Files Only)

Scanned Files

  • python/07-ux-demos/triage-agent/README.md
  • python/07-ux-demos/triage-agent/backend/main.py
  • python/07-ux-demos/triage-agent/backend/requirements.txt
  • python/07-ux-demos/triage-agent/deploy/triage-demo.yaml
  • python/07-ux-demos/triage-agent/frontend/craco.config.js
  • python/07-ux-demos/triage-agent/frontend/src/components/ChatInterface.js
  • python/07-ux-demos/triage-agent/start.sh

Security Scan Results

Critical High Medium Low Info
0 0 0 0 0

Threshold: High

No security issues detected in your changes. Great job!

This scan only covers files changed in this PR.

strandly-the-agent

This comment was marked as outdated.

@JackYPCOnline

Copy link
Copy Markdown
Contributor Author

@strandly-the-agent can you re-review this PR?

@strandly-the-agent strandly-the-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JackYPCOnline Approve: both findings are fixed, and I re-ran the bypass at e125ece. It no longer works.

  • 🔴 /mcp/logs leak: fixed. I ran the same repro against Bedrock, with a victim chatting and reloading their history. /mcp/logs now has 0 full UUIDs and none of the victim's text (name, DOB, symptoms). session_id and message_preview are gone from details, and the IDs in messages are cut to 709df529….
  • 🟡 /agents/status listing: fixed. The route is removed and now returns 404.

I also tried to get around the fix: uppercase, urn:uuid:, {…} and no-dash IDs all go through canonical_session_id first, so they're redacted too. The remaining 8-character prefix still leaves about 90 random bits, so it doesn't make a session guessable. I found no other route or log entry that exposes an ID or user text.

What's left is what the README warning already says: there's no user auth, so this protects sessions only by keeping their IDs secret. That's fine for a demo.

Verification
  • Backend ran on 127.0.0.1:8000 at head e125ece. pip install -r requirements.txt worked on 3.13 without numpy/pandas, and nothing under backend/ imports them.
  • Repro output: GET /sessions 404, GET /agents/status 404, 24 log entries, 0 full UUIDs, victim UUID present 0 times, user text present 0 times.
  • Artifacts: strands-agents/samples/pr/346/repro.sh and strands-agents/samples/pr/346/repro-output.txt
  • Not re-checked: the CloudFormation stack (not deployed, same as before).

@JackYPCOnline
JackYPCOnline marked this pull request as ready for review November 9, 2026 22:20
@JackYPCOnline
JackYPCOnline enabled auto-merge (squash) November 9, 2026 22:21

@mehtarac mehtarac left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the fix, LGTM!

@JackYPCOnline
JackYPCOnline merged commit fdb8c1e into main Nov 10, 2026
6 checks passed
@JackYPCOnline
JackYPCOnline deleted the fix/triage-agent-session-auth branch November 10, 2026 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants