Skip to content

Cherry Pick OData filter format in JWT string claims (#3510)#3528

Merged
RubenCerna2079 merged 3 commits intorelease/2.0from
dev/aaronburtle/Cherry-Pick-3510
May 7, 2026
Merged

Cherry Pick OData filter format in JWT string claims (#3510)#3528
RubenCerna2079 merged 3 commits intorelease/2.0from
dev/aaronburtle/Cherry-Pick-3510

Conversation

@aaronburtle
Copy link
Copy Markdown
Contributor

@aaronburtle aaronburtle commented May 7, 2026

Why make this change?

Closes #3527

What is this change?

Cherry pick #3510

How was this tested?

New tests run against main, and the current test suite.

## Why make this change?

Fixes the format of the OData filter in JWT string claims.

## What is this change?

In `AuthorizationResolver` we now escape embedded single quotes in claim
values by doubling them, before we wrap the value in single quotes for
OData substitution. This conforms to the OData 4.01 ABNF rule for string
literals (Section 7: Literal Data Values).

Policy: `@item.col1 eq @claims.userId`
Claim `userId` value: `alice' or 1 eq 1 or '`

| | Resulting OData predicate |
| --- | --- |
| Before | `col1 eq 'alice' or 1 eq 1 or ''` <- injects `or 1 eq 1`,
bypassing row-level auth |
| After | `col1 eq 'alice'' or 1 eq 1 or '''` <- attacker payload
contained inside a single string literal |

## How was this tested?

New parameterized test
`DbPolicy_StringClaim_SingleQuotesEscaped_PreventsODataInjection` in
`src/Service.Tests/Authorization/AuthorizationResolverUnitTests.cs`
covers:

- Active OR-predicate injection attempt is neutralized.
- Legitimate apostrophe-bearing value (e.g. `O'Brien`) is safely
escaped.
- Value composed solely of single quotes is fully escaped.
- Value with no single quotes is unchanged aside from the enclosing
quotes (no regression).

## Sample Request(s)

```json
{
  "entities": {
    "Note": {
      "source": "dbo.Notes",
      "permissions": [
        {
          "role": "authenticated",
          "actions": [
            {
              "action": "read",
              "policy": { "database": "@item.ownerId eq @claims.userId" }
            }
          ]
        }
      ]
    }
  }
}
```

Reproduction - `userId` claim value of `alice' or 1 eq 1 or '`:

```http
GET /api/Note HTTP/1.1
Authorization: Bearer <jwt-with-crafted-userId-claim>
X-MS-API-ROLE: authenticated
```

- Before fix: the engine emitted `WHERE ownerId = 'alice' or 1 eq 1 or
''`, returning rows owned by other users.
- After fix: the engine emits `WHERE ownerId = 'alice'' or 1 eq 1 or
'''`, which compares against the literal string `alice' or 1 eq 1 or '`
and returns no unauthorized rows.

Co-authored-by: Souvik Ghosh <souvikofficial04@gmail.com>
Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
(cherry picked from commit 0512b00)
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR cherry-picks a security fix to ensure JWT string-typed claim values are safely substituted into database authorization (OData) policies by escaping embedded single quotes, preventing OData filter injection via claim contents.

Changes:

  • Escape single quotes in ClaimValueTypes.String claim values by doubling them per OData 4.01 string literal rules.
  • Add unit tests covering injection-like and legitimate single-quote-containing claim values to validate safe policy substitution.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Core/Authorization/AuthorizationResolver.cs Escapes embedded single quotes in string claim literals before substituting into DB policies.
src/Service.Tests/Authorization/AuthorizationResolverUnitTests.cs Adds unit tests verifying single-quote escaping prevents OData predicate injection and preserves valid values.

@RubenCerna2079 RubenCerna2079 enabled auto-merge (squash) May 7, 2026 02:50
@RubenCerna2079 RubenCerna2079 disabled auto-merge May 7, 2026 04:43
@RubenCerna2079 RubenCerna2079 merged commit fc3fd97 into release/2.0 May 7, 2026
12 checks passed
@github-project-automation github-project-automation Bot moved this from Review In Progress to Done in Data API builder May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants