Use the \Q sequence, which escapes every non-literal by adding backslashes:
$line =~ s:\Q$source:$target: ;
However, beware of UTF-8. If your $source string contains multibyte characters, this won't work as it treats the string as a sequence of octets (shame on perl for this!).
If $source contains any multibyte characters, you'll have to add the backslashes yourself:
$source =~ s/(\W)/\\$1/g;
$line =~ s:$source:$target: ;
I've not tested it but think it should work. Hope this helps.