I just tried your input on Logstash 6.4.0, and it seems to work as intended.
╭─{ yaauie@castrovel:~/src/elastic/discuss-scratch/150047-mutate-gsub-trailing-colon }
╰─○ echo '{"app_name":"dashboard_webapp:"}' | ${LOGSTASH_HOME}/bin/logstash -e 'input { stdin { codec => json } } filter { mutate { gsub => ["app_name", ":$", ""] } }'
Sending Logstash logs to /Users/yaauie/src/elastic/releases/logstash-6.4.0/logs which is now configured via log4j2.properties
[2018-09-26T17:43:45,404][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified
[2018-09-26T17:43:45,913][INFO ][logstash.runner ] Starting Logstash {"logstash.version"=>"6.4.0"}
[2018-09-26T17:43:48,264][INFO ][logstash.pipeline ] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>8, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50}
[2018-09-26T17:43:48,383][INFO ][logstash.inputs.stdin ] Automatically switching from json to json_lines codec {:plugin=>"stdin"}
[2018-09-26T17:43:48,436][INFO ][logstash.pipeline ] Pipeline started successfully {:pipeline_id=>"main", :thread=>"#<Thread:0x3b09a39d run>"}
[2018-09-26T17:43:48,505][INFO ][logstash.agent ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2018-09-26T17:43:49,079][INFO ][logstash.agent ] Successfully started Logstash API endpoint {:port=>9600}
{
"app_name" => "dashboard_webapp",
"@version" => "1",
"@timestamp" => 2018-09-26T17:43:48.578Z,
"host" => "castrovel.local"
}
[2018-09-26T17:43:49,195][INFO ][logstash.pipeline ] Pipeline has terminated {:pipeline_id=>"main", :thread=>"#<Thread:0x3b09a39d run>"}
[success (21.000s)]
What version of Logstash are you using?
${LOGSTASH_HOME}/bin/logstash --version
What version of the Mutate filter plugin does it have loaded?
${LOGSTASH_HOME}/bin/logstash-plugin list --verbose logstash-filter-mutate