Express res.sendfile arrojando error prohibido

160

Tengo este codigo:

res.sendfile( '../../temp/index.html' )

Sin embargo, arroja este error:

Error: Forbidden
at SendStream.error (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:145:16)
at SendStream.pipe (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:307:39)
at ServerResponse.res.sendfile (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/response.js:339:8)
at exports.boot (/Users/Oliver/Development/Personal/Reader/server/config/routes.js:18:9)
at callbacks (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:161:37)
at param (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:135:11)
at pass (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:170:5)
at Object.router (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:33:10)
at next (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/connect/lib/proto.js:199:15)

¿Alguien puede decirme por qué podría ser esto?


fuente
3
Creo que es por el camino relativo; el "../" se considera malicioso. Primero resuelva la ruta local, luego llameres.sendfile
Joe
¿Cómo se resuelve la ruta local?
44
path.resolveDebe hacer lo que necesita.
Joe
1
Eso lo hizo. ¿Quieres pasar eso como respuesta?

Respuestas:

286

Creo que es por el camino relativo; el "../" se considera malicioso. Primero resuelva la ruta local, luego llame res.sendfile. Puede resolver el camino de path.resolveantemano.

var path = require('path');
res.sendFile(path.resolve('temp/index.html'));
Joe
fuente
31
más detalles serían útiles aquí para novatos como yo
Adam Waite
55
Express considera las rutas relativas sendfilecomo malas. A menos que especifique el rootparámetro de directorio, como se ve aquí: github.com/visionmedia/express/issues/1465
Joe
2
var ruta = require ('ruta');
Matt Harrison el
1
si el codigo final !!
SuperUberDuper
2
Actualización @MattHarrison ES6, para paquetes de importaciones, constse prefiere sobrevar
Nino Filiu
39

Esta respuesta reúne la información de las otras respuestas / comentarios.

Depende de si desea incluir algo relativo al directorio de trabajo del proceso (cwd) o al directorio del archivo. Ambos usan la path.resolvefunción (poner var path = require('path')en la parte superior del archivo.

  • relativo a cwd: path.resolve('../../some/path/to/file.txt');
  • relativo al archivo: path.resolve(__dirname+'../../some/path/to/file.txt');

Al leer el enlace del comentario de @ Joe, parece que las rutas relativas son un riesgo de seguridad si acepta la entrada del usuario para la ruta (por ejemplo, sendfile('../.ssh/id_rsa')podría ser el primer intento de un pirata informático).

derekdreery
fuente
1
Como novato, quiero saber cómo llegó el escenario hacker aquí.
bharath muppa
2
Si accidentalmente permite que el usuario ingrese la ruta del archivo que desea descargar, podría descargar cualquier archivo en su sistema (di el ejemplo de una clave privada ssh, lo que les daría la capacidad de pretender ser su PC ( hombre en el medio, etc.). Tener la restricción .. no permite esta posibilidad ya que solo se puede acceder a los archivos del sitio web.
derekdreery
30

La documentación de Express sugiere hacerlo de una manera diferente, y en mi opinión tiene más sentido que la solución actual.

res.sendFile('index.html', {root: './temp'});

La opción raíz parece configurarse ./como el directorio raíz de su proyecto. Por lo tanto, no puedo decir completamente dónde está su archivo en relación con la raíz del proyecto, pero si su carpeta temporal está allí, puede establecerla ./tempcomo la raíz del archivo que está enviando.

tenor528
fuente
1
Esto es cierto, pero utiliza sendFile (F mayúscula, compatible con Express v4.8.0 en adelante) en lugar del anterior sendfile que estaba utilizando el OP. Solo digo ... =]
RemyNL
Ahh ... buena captura. No noté esta pequeña diferencia. También me pregunto si la respuesta seleccionada no funciona porque se usa .sendfilesino porque se basa completamente en otra cosa (ruta). Gracias por señalar esto.
tenor528
Simple y eficiente. ¡Gracias! ¡Esto funcionó para mí perfectamente!
Emanuela Colta