Skip to content

Support nested map claims in Cedar authorization for act claim#5713

Open
jhrozek wants to merge 1 commit into
mainfrom
cedar-nested-map-claims
Open

Support nested map claims in Cedar authorization for act claim#5713
jhrozek wants to merge 1 commit into
mainfrom
cedar-nested-map-claims

Conversation

@jhrozek

@jhrozek jhrozek commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Cedar policies flatten JWT claims into context/principal attributes, but nested map claims were silently dropped during conversion — most notably an RFC 8693 actor-delegation claim (act), shaped like {"act": {"sub": "spiffe://..."}}. This meant Cedar could never express delegation-aware policies such as "the user can write, but an agent acting on the user's behalf can only read."

This PR adds recursive conversion of nested map/array claims into nested Cedar records/sets, bounded by a depth cap (maxClaimNestingDepth = 10) so a claim from an unverified upstream JWT can't drive unbounded recursion. With this change, policies can now do:

permit(principal, action == Action::"call_tool", resource == Tool::"deploy")
when {
    context.claim_sub == "user@example.com" &&
    context has claim_act &&
    context.claim_act.sub like "spiffe://toolhive.dev/ns/agents/sa/*"
};
  • Adds maxClaimNestingDepth guard and depth-tracked variants of convertMapToCedarRecord/convertToCedarValue
  • Generalizes array conversion to recurse through the same converter (arrays of maps/arrays are now supported; previously silently dropped)
  • Adds test coverage for nested-map conversion, the depth-limit boundary, and delegation-style permit/forbid policies gated on act

Refs #5194

Type of change

  • Bug fix
  • New feature
  • Refactoring (no behavior change)
  • Dependency update
  • Documentation
  • Other (describe):

Test plan

  • Unit tests (task test)
  • E2E tests (task test-e2e)
  • Linting (task lint-fix)
  • Manual testing (describe below)

Does this introduce a user-facing change?

Yes. Cedar policies can now read nested JWT claims via dot-access (e.g. context.claim_act.sub), not just flat scalar/array claims. Claims nested more than 10 levels deep are silently dropped (with a warning logged) rather than causing unbounded recursion.

Special notes for reviewers

Generated with Claude Code

Add map[string]interface{} case to convertToCedarValue so that nested
JWT claims like the RFC 8693 act claim ({"sub": "spiffe://..."}) are
converted to Cedar Records instead of being silently dropped.

This enables delegation policies such as:
  principal.claim_act.sub like "spiffe://toolhive.dev/ns/agents/sa/*"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the size/M Medium PR: 300-599 lines changed label Jul 2, 2026
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.67%. Comparing base (2aca563) to head (557fb9c).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5713      +/-   ##
==========================================
+ Coverage   70.63%   70.67%   +0.04%     
==========================================
  Files         667      667              
  Lines       67607    67622      +15     
==========================================
+ Hits        47752    47792      +40     
+ Misses      16399    16359      -40     
- Partials     3456     3471      +15     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant