Skip to content

fix(server): gate issue_info attachment metadata on capability - #9

Merged
plusky merged 1 commit into
mainfrom
fix/issue-info-attachments-r2
Aug 8, 2026
Merged

fix(server): gate issue_info attachment metadata on capability#9
plusky merged 1 commit into
mainfrom
fix/issue-info-attachments-r2

Conversation

@plusky

@plusky plusky commented Aug 8, 2026

Copy link
Copy Markdown
Owner

issue_info re-fetched Read-granted issues with no field selection and served the body as-is, so fields.attachment — filenames, sizes, authors, content URLs — reached the client even when the policy withheld Capability::Attachments. list_attachments gates exactly that metadata on the capability, so the capability was enforced on two of the three routes to the same data. I6 says read implies summary and nothing else.

issue_info now strips fields.attachment unless the grant includes attachments, on both the full-body path and the projection fallback path; the removal is not reported to the client. DESIGN.md records the Read-vs-Attachments field contract.

Scope note: the finding's broader "review other field families on the unfiltered fetch" item is deliberately not part of this PR.

Invariants: I6; removal invisible to the client (I3 in spirit); composes with the existing I14 link scrub on the same path.

Tests: pins that read-without-attachments serves the issue without fields.attachment while the rest of the body is intact; confirmed to fail against the unfixed code. (This PR passed adversarial review on its second round — the first round was refuted and revised.)

Process: AI-assisted — implemented and independently adversarially reviewed against docs/DESIGN.md (final verdict: approve, with an empirical pre-fix-failure check). Full verification suite green at the commit.

issue_info's Read path fetches the issue with no field projection, so
Jira's default navigable field set — attachment, comment, worklog —
reached the client on a bare read grant, bypassing the capabilities
that gate those families on every other route.

Guard::scrub_gated_fields now runs on both the full-body Read path and
the summary/projection fallback before a body is served (I6):

- fields.attachment requires Capability::Attachments — filenames,
  sizes, and content URLs are reachable only through the attachments
  capability, matching list_attachments/download_attachment.
- fields.comment requires Capability::Comments, matching issue_comments;
  when granted, restricted-visibility comments are still removed
  because issue_info has no per-call restricted opt-in, so I5's dual
  opt-in cannot be satisfied on this route.
- fields.worklog is always stripped: no v1 capability covers worklog
  content, and ungoverned content is stripped, not served (I4).
- count-only fields.watches / fields.votes stay in the read body
  (deliberate: counts, no identities, no restricted content).

Removals are silent to the client (I3 spirit): no markers, and the
embedded comment total tracks the served list. The scrub composes with
the existing I14 link scrub on the same path. DESIGN.md I6 records the
resulting Read field contract.

Covered by guard unit tests and MCP-level wiremock tests: read without
attachments/comments serves the body minus those families while
list_attachments and issue_comments stay uniformly denied (I2), a
granted comments capability still filters the restricted comment, and
a granted attachments capability serves the metadata.

Invariants touched: I2, I3 (spirit), I4, I5, I6, I14.
@plusky plusky added security Guard, key custody, or disclosure surface ai-assisted Found or drafted with AI assistance; claims verified against source, review independently labels Aug 8, 2026
@plusky
plusky enabled auto-merge (rebase) August 8, 2026 19:53
@plusky
plusky merged commit 0219724 into main Aug 8, 2026
11 checks passed
@plusky
plusky deleted the fix/issue-info-attachments-r2 branch August 8, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted Found or drafted with AI assistance; claims verified against source, review independently security Guard, key custody, or disclosure surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant