microsoft / microsoft/AdaptiveCards

[Security] ReDoS vulnerability in StringWithSubstitutions.getReferencedInputs - input.id injected into regex without escaping

Open Beginner friendly
#9,369 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Area-Schema Bug
Dominant language
C#
Stars
2k
Forks
595
Avg merge
1d 19h
Merged PRs (30d)
1

Description

Target Application

Windows Widgets, Microsoft Teams, Outlook, any host using AdaptiveCards JS renderer with Action.Http registered

Application Operating System

Windows

Schema Version

1.5

Problem Description

In shared.ts line 87, the method StringWithSubstitutions.getReferencedInputs() builds a regular expression by directly concatenating input.id from the card JSON payload into a new RegExp() constructor without escaping regex metacharacters.

The vulnerable code:
const matches = new RegExp("\{{2}(" + input.id + ").value\}{2}", "gi").exec(this._original);

input.id comes from untrusted card JSON. An attacker can set input.id to a value like (a+)+ which contains regex quantifiers. When this regex is executed against a URL template containing a near-match pattern, the regex engine enters catastrophic backtracking (exponential time complexity).

This code path is triggered when a user clicks an Action.Http button. Action.Http is not registered in the default GlobalRegistry, so only hosts that explicitly register HttpAction are affected. Standard actions like Action.Submit and Action.Execute use a different code path (internalGetReferencedInputs in SubmitActionBase) that does not call StringWithSubstitutions.getReferencedInputs and is NOT vulnerable.

Measured impact with 28 characters of near-match content in the URL template:

Unfixed: 13,350ms (browser completely frozen)
Fixed with escapeRegExp: 0ms
The freeze duration doubles with every 2 additional characters. At 40 characters it would take hours.

Expected Outcome

The renderer should safely handle any value of input.id without freezing. Regex metacharacters in input.id should be escaped before being used in a RegExp constructor, or a non-regex approach should be used for matching.

Actual Outcome

When a card contains an Input element with id set to a regex pattern like (a+)+ and an Action.Http with a URL template containing a near-match string like {{aaaaaaaaaaaaaaaaaaaaaaaaaaaaXXXXX}}, clicking the action button causes the browser or widget host to freeze for seconds to minutes due to catastrophic regex backtracking. CPU spikes to 100% on a single core.

Card JSON
{
  "type": "AdaptiveCard",
  "version": "1.5",
  "body": [
    {
      "type": "Input.Text",
      "id": "(a+)+",
      "label": "Enter your name"
    }
  ],
  "actions": [
    {
      "type": "Action.Http",
      "title": "Send",
      "method": "POST",
      "url": "https://example.com/api?name={{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaXXXXX}}"
    }
  ]
}
Repro Steps
  1. Register HttpAction in the global registry: GlobalRegistry.actions.register("Action.Http", HttpAction)
  2. Parse the card JSON shown above using AdaptiveCard.parse()
  3. Render the card using AdaptiveCard.render()
  4. Click the "Send" button
  5. The browser or widget host freezes for 13+ seconds (with 28 'a' characters in the URL template). Increasing the count of 'a' characters makes it exponentially worse.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at shared.ts line 87 and reproduce the supplied card through AdaptiveCard.parse(), AdaptiveCard.render(), and the registered Action.Http click path. Done means the near-match URL template completes without freezing when input.id contains regex metacharacters; check the relevant renderer tests if available.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
frontend, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.