diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d0ff70d..7beb5dc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.6.0-beta-3] - 2026-09-01 +## [1.6.0-beta-3] - 2026-09-02 ### Fixed - OAR002 - Detect an attribute or container written with no value (`roles:`), the `~`/`Null`/`NULL` spellings of null, and anchor map-form scope defects on the scope key. -- +- OAR044 - MediaTypeCheck - Made the media type regex quantifiers possessive to prevent ReDoS with no change to matching. + ### Added - OAR060 - QueryParametersOptional - New `path-exclusions` rule property (default `/status`): a comma-separated list of exact, case-sensitive paths the rule must not fire on. diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheck.java index 39656827..b3446786 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheck.java @@ -45,11 +45,11 @@ public class OAR044MediaTypeCheck extends BaseCheck { private final ExternalRefHandler handleExternalRef = new ExternalRefHandler(); private static final String RESTRICTED_NAME = "[a-zA-Z0-9][a-zA-Z0-9.!#$&^_+\\-]*"; - private static final String OWS = "[ \\t]*"; - private static final String TOKEN = "[a-zA-Z0-9!#$%&'*+\\-.^_`|~]+"; - private static final String QUOTED_STRING = "\"(?:[^\"\\\\]|\\\\.)*\""; + private static final String OWS = "[ \\t]*+"; + private static final String TCHARS = "[a-zA-Z0-9!#$%&'*+\\-.^_`|~]++"; + private static final String QUOTED_STRING = "\"(?:[^\"\\\\]|\\\\.)*+\""; private static final String PARAMETERS = - "(?:" + OWS + ";" + OWS + TOKEN + "=(?:" + TOKEN + "|" + QUOTED_STRING + "))*"; + "(?:" + OWS + ";" + OWS + TCHARS + "=(?:" + TCHARS + "|" + QUOTED_STRING + "))*+"; @VisibleForTesting static final Pattern MIME_TYPE_PATTERN = Pattern.compile( diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheckTest.java index ae71be53..5a70f94a 100644 --- a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheckTest.java +++ b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR044MediaTypeCheckTest.java @@ -6,6 +6,8 @@ import org.sonar.api.rules.RuleType; import apiaddicts.sonar.openapi.BaseCheckTest; +import static org.junit.Assert.assertFalse; + public class OAR044MediaTypeCheckTest extends BaseCheckTest { @Before @@ -36,6 +38,13 @@ public void verifyInV32() { verifyV32("media-type"); } + @Test(timeout = 2000) + public void verifyNoBacktrackingOnLongInput() { + String malicious = "application/json;x=\"" + "a".repeat(500_000); + assertFalse(OAR044MediaTypeCheck.MEDIA_RANGE_PATTERN.matcher(malicious).matches()); + assertFalse(OAR044MediaTypeCheck.MIME_TYPE_PATTERN.matcher(malicious).matches()); + } + @Override public void verifyRule() { assertRuleProperties("OAR044 - MediaType - Media types SHOULD conform to the RFC.", RuleType.BUG, Severity.BLOCKER, tags("format"));