Skip to content

feat(agents): canvas routes join the agent-token allowlist (#1800 slice 2)#1825

Merged
jaylfc merged 2 commits into
devfrom
feat/lead-identity-mw-allowlist
Jul 15, 2026
Merged

feat(agents): canvas routes join the agent-token allowlist (#1800 slice 2)#1825
jaylfc merged 2 commits into
devfrom
feat/lead-identity-mw-allowlist

Conversation

@jaylfc

@jaylfc jaylfc commented Jul 14, 2026

Copy link
Copy Markdown
Owner

slice 2 of #1800 identity epic, DO NOT MERGE (held for full-set review)


Summary by Gitar

  • Authentication middleware:
    • Added _AGENT_CANVAS_ROUTES and _is_agent_canvas_path to include specific canvas endpoints in the agent-token allowlist.
    • Updated AuthMiddleware to authorize these routes via bearer tokens, explicitly excluding sensitive PATCH operations.
  • Testing:
    • Added comprehensive unit tests in test_auth_middleware.py verifying both route matching logic and middleware access control.

This will update automatically on new commits.

Summary by CodeRabbit

  • New Features

    • Added support for agent-token access to approved project canvas operations, including viewing and removing canvas elements.
    • Supported canvas routes now work with eligible bearer-token authentication.
  • Bug Fixes

    • Improved authorization safeguards to reject unsupported methods, malformed paths, nested routes, and unauthorized canvas permission changes.
    • Corrected snapshot filename matching so similarly named paths are not incorrectly accepted.

…ce 2)

Add _AGENT_CANVAS_ROUTES allowlist and _is_agent_canvas_path helper so
registry Bearer tokens reach the canvas element list/create/delete,
snapshot PNG/TLDR, and SSE stream endpoints. PATCH elements and
PATCH permissions remain session-only.

Docs-Reviewed: middleware canvas-route allowlist per design doc lead-agent-identity-and-canvas-access.md
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c7cf5af9-ae3f-40f1-bab0-2bea0e431ed8

📥 Commits

Reviewing files that changed from the base of the PR and between 70956ab and be2ed6e.

📒 Files selected for processing (2)
  • tests/test_auth_middleware.py
  • tinyagentos/auth_middleware.py

📝 Walkthrough

Walkthrough

Adds an exact allowlist matcher for project canvas routes and extends registry-JWT candidate handling to those routes. Tests cover permitted methods and paths, malformed or unsupported paths, request state, and unauthorized dispatch behavior.

Changes

Canvas agent authorization

Layer / File(s) Summary
Canvas route allowlist and dispatch
tinyagentos/auth_middleware.py, tests/test_auth_middleware.py
Defines exact method/path matching for canvas endpoints, integrates the matcher into middleware dispatch, and tests successful and denied registry-JWT candidate requests.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AuthMiddleware
  participant DownstreamHandler
  Client->>AuthMiddleware: Bearer request to canvas route
  AuthMiddleware->>AuthMiddleware: Match method and path allowlist
  AuthMiddleware->>DownstreamHandler: Dispatch allowed request
  AuthMiddleware-->>Client: Return 401 for denied route
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding canvas routes to the agent-token allowlist.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lead-identity-mw-allowlist

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@gitar-bot

gitar-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

Comment thread tinyagentos/auth_middleware.py Outdated
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/elements$")),
("POST", re.compile(rf"^/api/projects/{_SEG}/canvas/elements$")),
("DELETE", re.compile(rf"^/api/projects/{_SEG}/canvas/elements/{_SEG}$")),
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot.png$")),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Unescaped . in the snapshot regex is a wildcard, not a literal dot

In ^/api/projects/{_SEG}/canvas/snapshot.png$ the . matches any single character. Any path such as /api/projects/x/canvas/snapshotXpng (or a future sibling route like snapshot-apng) would also satisfy this allowlist entry. On a security allowlist this is an over-broad match. Escape the literal dot.

Suggested change
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot.png$")),
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot\.png$")),

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Comment thread tinyagentos/auth_middleware.py Outdated
("POST", re.compile(rf"^/api/projects/{_SEG}/canvas/elements$")),
("DELETE", re.compile(rf"^/api/projects/{_SEG}/canvas/elements/{_SEG}$")),
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot.png$")),
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot.tldr$")),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Unescaped . in the snapshot regex is a wildcard, not a literal dot

Same issue as the snapshot.png entry: .tldr should be \.tldr so only the literal suffix matches. As written, snapshot_tldr or similar could satisfy the pattern.

Suggested change
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot.tldr$")),
("GET", re.compile(rf"^/api/projects/{_SEG}/canvas/snapshot\.tldr$")),

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • tinyagentos/auth_middleware.py
  • tests/test_auth_middleware.py

Incremental review (since 5c3d5e2): The two prior SUGGESTION findings — unescaped . in the snapshot.png / snapshot.tldr allowlist regexes (auth_middleware.py lines 65/66) — were resolved in commit be2ed6e (PATCH 2/2). Both dots are now escaped as \.png and \.tldr, and regression tests were added for the near-miss forms (snapshotXpng, snapshot_png, snapshotXtldr) plus the single-element GET boundary. No new issues were introduced by the incremental change.

Security note (informational, unchanged): The middleware still passes any non-local Bearer token through to the canvas routes and relies on each route handler to verify the registry JWT and its canvas_read/canvas_write scope. The allowlist keeps PATCH element/permission routes session-only and is properly anchored, so no skeleton-key exposure is introduced. Ensure the canvas route handlers enforce scope, since the middleware does not distinguish read vs. write tokens.

Previous Review Summary (commit 5c3d5e2)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 5c3d5e2)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
tinyagentos/auth_middleware.py 65 Unescaped . in snapshot.png regex is a wildcard; escape as \.png to avoid over-broad allowlist matches
tinyagentos/auth_middleware.py 66 Unescaped . in snapshot.tldr regex is a wildcard; escape as \.tldr
Files Reviewed (2 files)
  • tinyagentos/auth_middleware.py - 2 issues
  • tests/test_auth_middleware.py - 0 issues

Security note (informational, not a defect): As with the existing _AGENT_TOKEN_PATHS / _AGENT_TASK_ROUTES contract, the middleware passes any non-local Bearer token through to the canvas routes and relies entirely on each route handler to verify the registry JWT and its canvas_read/canvas_write scope. The allowlist correctly keeps PATCH element/permission routes session-only and is properly anchored, so no skeleton-key exposure is introduced. Ensure the canvas route handlers enforce scope, since the middleware does not distinguish read vs. write tokens.

Fix these issues in Kilo Cloud


Reviewed by hy3:free · Input: 72.2K · Output: 8K · Cached: 125.1K

Adversarial review caught that snapshot.png and snapshot.tldr used an
unescaped dot, so the regex treated it as a wildcard and a near-miss like
snapshotXpng would match the agent-token allowlist. Escape both dots so
the match is literal, and add regression tests for the near-miss forms
plus the single-element GET boundary.

Docs-Reviewed: harden canvas allowlist regex anchoring per lead-agent-identity-and-canvas-access.md
@jaylfc

jaylfc commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

Folded an adversarial-review finding: the snapshot.png and snapshot.tldr allowlist regexes used an unescaped dot, so the pattern matched a near-miss like snapshotXpng. Escaped both dots for a literal match and added regression tests (snapshotXpng, snapshot_png, snapshotXtldr, and the single-element GET boundary). Note on the reviewer's other flag (agent-token branch sits before the first-boot onboarding gate): that ordering is pre-existing for the task and A2A agent routes, and it is not a bypass because the branch only passes through while the route itself verifies the registry JWT and fails closed, and no valid agent token can exist on an unconfigured system. Not folding it here; it can be a separate defense-in-depth note if we want the gate moved ahead of the pass-through.

@jaylfc
jaylfc merged commit d70128e into dev Jul 15, 2026
9 checks passed
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.

1 participant