Работая с public_send
, вы можете изменить соответствующие строки на:
if workflow.public_send("can_#{incoming_status}?")
# update status
workflow.public_send(incoming_status.to_s)
# ...
Примечание о безопасности и рисках
workflow.public_send("can_#{xyz}?")
может вызывать только методы на workflow
, которые public
и начинаются с префикса can_
и заканчиваются ?
. Вероятно, это лишь небольшое количество методов, и вы можете легко решить, хотите ли вы разрешить все эти методы.
workflow.public_send("#{incoming_status'})
отличается тем, что разрешает все открытые методы для workflow
- даже destroy
. Это означает, что использовать это без "can_#{incoming_status}?"
, вероятно, плохая идея. Или вы должны хотя бы сначала проверить, находится ли incoming_status
в белом списке разрешенных методов.
eval
является наихудшим, потому что он будет оценивать всю строку без какого-либо контекста (например, такой объект, как workflow
). Снимки у вас есть eval("workflow.#{incoming_status}")
без предварительной проверки, действительно ли разрешено incoming_status
. Если кто-то затем отправляет incoming_status
, например, "to_s; system('xyz')"
, тогда xyz
может быть чем угодно - например, командами для отправки скрытого файла по электронной почте, для установки бэкдора или для удаления некоторых файлов.