daattali / shinyjs

💡 Easily improve the user experience of your Shiny apps in seconds
https://deanattali.com/shinyjs
Other
734 stars 119 forks source link

disable() should remove bindings #269

Closed Mkranj closed 1 year ago

Mkranj commented 1 year ago

When you disable a UI element with shinyjs::disable, it works great in that it prevents the user from further manipulating that element. However, I have question that's security related and deals with manipulating a running app with Javascript. Please check out this example app:

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  selectInput("my_options", "Select something", choices = 1:10),
  actionButton("disable_input", "Disable selecting"),
  textOutput("results")
)

server <- function(input, output, session) {
  observeEvent(input$disable_input, {
    shinyjs::disable("my_options")
  })

  output$results <- renderText({
    input$my_options
  })
}

shinyApp(ui, server)

When you disable the selectInput, it works as expected. What I'm worried about, is someone opening the console in their browser and typing something like Shiny.setInputValue("my_options", 5) or Shiny.setInputValue("my_options", 15). Both of these change the input value even when the input is disabled. It's especially disconcerting since the second one is not supposed to be selectable in any case.
I believe you can imagine that this might introduce vulnerabilities. Especially since the id of elements is almost always visible in HTML. Is it possible for the disable() function to "cut" the bindings between the element and the value?

There's a tip for controlling for impossible values in Mastering Shiny, so this bit seems to be preventable. Since shinyjs deals even more with the Javascript side of things, I'd love to hear if you have any ideas for how to secure shiny apps.

daattali commented 1 year ago

That's a valid concern, but it's entirely out of scope for shinyjs. Shinyjs, as the name says, concerns itself with making it easy to perform javascript operations - which are generally UI related, not security related. This package does not attempt to solve any security issues. Anything security related should always be handled in the server, not in the client (which is where javascript is used). Using disable() or any other shinyjs functions isn't causing any security issues, those issues are always there whether you use shinyjs or not. Absolutely any input you have in a shiny app can be manipulated through the javasript console, so it's always good practice to verify values in the server.