microsoft / microsoft/AdaptiveCards
[Security] ReDoS vulnerability in StringWithSubstitutions.getReferencedInputs - input.id injected into regex without escaping
Nobody has claimed this yet.
- 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
- Register HttpAction in the global registry: GlobalRegistry.actions.register("Action.Http", HttpAction)
- Parse the card JSON shown above using AdaptiveCard.parse()
- Render the card using AdaptiveCard.render()
- Click the "Send" button
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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