(Solo para resumir mi respuesta a esta pregunta duplicada en SO y sus comentarios ...)
Es ciertamente una mala práctica, y también puede ser un problema legal importante.
Debido a que tanto el usuario como su servicio técnicamente han tenido acceso a la clave privada, ya no puede garantizar quién fue el firmante real ante un tercero.
¿Conoces alguna biblioteca javascript que firme documentos xml, pdf y office? De esta manera, la clave privada solo se usaría en el lado del cliente.
No haga criptografía de JavaScript . No podrá demostrar al usuario lo que hace su código (aún podría enviar la clave). Que yo sepa, algunos de los proyectos de WebCrypto intentaban solucionar algunos de estos problemas (por ejemplo, al permitir que un código JS use la clave privada almacenada en el navegador sin dejarlo salir), pero aún no está listo, y no resuelve todos los problemas (por ejemplo, demostrando a los usuarios lo que están firmando con esa clave privada).
Y, por supuesto, el show-stopper técnico ...
La mayoría de los mecanismos de tarjetas inteligentes no le permiten acceder a la propia clave privada (a menudo por diseño), por lo que de alguna manera tendría que interactuar con la API de firma para la tarjeta.
Esa API no le dará realmente la clave privada, solo le permitirá usarla para firmar algo, el procesamiento se realiza en la propia tarjeta. Por lo tanto, cualquier plan para enviar la clave privada a algún lugar o tener algún código (que no use esta API) no funcionará.
Si bien el navegador puede utilizar el certificado en tarjetas inteligentes para la autenticación del certificado del cliente, porque los navegadores se implementan para admitir esto como parte de su propia interfaz de usuario (nada que ver con ninguna página web que pueda proporcionar), no creo hay algo obvio al tener un script en tu página web para acceder a todo esto. (Esto también dejaría el problema de confiar en lo que realmente firma su código JS).