You can now vote for scripts to help people know if they're useful or not. Login or create an account to vote!


Block Unicode Bidirectional Control Characters


This merge check blocks any textual additions that include bidi control characters, as discussed in

Good to Know

  • This script must be configured as a Merge Check.
  • It will prevent merging of any Pull Requests that contain the addition of any bidi control character.
  • As it's possible that there are legitimate usages of these characters, in that case, you will need to have an administrator disable the merge check in order to merge.


  • Bitbucket Bitbucket (6.0 - 7.17)
  • ScriptRunner for Bitbucket ScriptRunner for Bitbucket (6.18.0)
import com.atlassian.bitbucket.content.AbstractChangeCallback import com.atlassian.bitbucket.content.AbstractDiffContentCallback import com.atlassian.bitbucket.content.Change import com.atlassian.bitbucket.content.ConflictMarker import com.atlassian.bitbucket.content.DiffSegmentType import com.atlassian.bitbucket.hook.repository.RepositoryHookResult import com.atlassian.bitbucket.pull.PullRequestChangesRequest import com.atlassian.bitbucket.pull.PullRequestDiffRequest import com.atlassian.bitbucket.pull.PullRequestService import com.atlassian.sal.api.component.ComponentLocator import javax.annotation.Nonnull import javax.annotation.Nullable import java.util.regex.Pattern def pullRequest = mergeRequest.pullRequest final bidiCharsPattern = Pattern.compile(/[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/) def pullRequestService = ComponentLocator.getComponent(PullRequestService) Set blockedFiles = [] def changeCallback = new AbstractChangeCallback() { @Override boolean onChange(@Nonnull Change change) throws IOException { pullRequestService.streamDiff(new PullRequestDiffRequest.Builder(pullRequest, change.path.toString()).build(), new AbstractDiffContentCallback() { private DiffSegmentType type @Override void onSegmentStart(@Nonnull DiffSegmentType type) throws IOException { this.type = type super.onSegmentStart(type) } @Override void onSegmentLine( @Nonnull String line, @Nullable ConflictMarker marker, boolean truncated ) { if (type == DiffSegmentType.ADDED) { if (bidiCharsPattern.matcher(line)) { blockedFiles << change.path.toString() } } } }) true } } pullRequestService.streamChanges(new PullRequestChangesRequest.Builder(pullRequest).withComments(false).build(), changeCallback) if (blockedFiles) { RepositoryHookResult.rejected("Merge rejected", "Diff contains illegal Unicode bidirectional characters in ${blockedFiles.join(', ')}") }
Discovered an issue? Report it here

Suggested for you