All you need to do is capture these contextual nodes in a special name “contextual”.

(heredoc_body) @contextual
(string) @contextual

I see. I'll give that a try.
 
But I don’t know about the bleeding you described in the very beginning. Do you still see it? Is there a recipe to reproduce it?

It might just be because of how the tree-sitter-bash grammar defines heredoc strings.

This are the steps to reproduce the issue on sh-mode:

;; build emacs from head of feature/tree-sitter branch
;; apply the attached patch.
;; launch emacs with: emacs -nw -Q
;;Write the forms bellow on *scratch* buffer)

(require 'treesit)
(add-to-list 'treesit-settings '(sh-mode t t))
(find-file "/tmp/heredoc-issue.sh")

;; contents of /tmp/heredoc-issue.sh file (also attached)

#!/usr/bin/env bash

cat <<EOF
heredoc string
EOF
echo "<<HELLO>>"

;; Then execute the commands below

ESC <                   ;; beginning-of-buffer
C-s                     ;; isearch-forward
heredoc                 ;; self-insert-command * 7
RET                     ;; newline
C-a                     ;; move-beginning-of-line
C-k                     ;; kill-line
C-n                     ;; next-line (At this point the echo command after EOF is fontified as heredoc string)
C-_                     ;; undo (After a short delay, the whole buffer is correctly fontified)

--
João Paulo L. de Carvalho
Ph.D Computer Science |  IC-UNICAMP | Campinas , SP - Brazil
Postdoctoral Research Fellow | University of Alberta | Edmonton, AB - Canada
joao.carvalho@ic.unicamp.br
joao.carvalho@ualberta.ca