Express res.sendfile lançant une erreur interdite

160

J'ai ce code:

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

Cependant, il jette cette erreur:

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)

Quelqu'un peut-il me dire pourquoi cela pourrait être?


la source
3
Je crois que c'est à cause du chemin relatif; le "../" est considéré comme malveillant. Résolvez d'abord le chemin local, puis appelezres.sendfile
Joe
Comment résolvez-vous le chemin local?
4
path.resolvedevrait faire ce dont vous avez besoin.
Joe
1
Cela l'a fait. Vous voulez passer cela comme une réponse?

Réponses:

286

Je crois que c'est à cause du chemin relatif; le "../" est considéré comme malveillant. Résolvez d'abord le chemin local, puis appelez res.sendfile. Vous pouvez résoudre le chemin avec path.resolveau préalable.

var path = require('path');
res.sendFile(path.resolve('temp/index.html'));
Joe
la source
31
plus de détails seraient utiles ici pour les débutants comme moi
Adam Waite
5
Express considère les chemins relatifs sendfilecomme mauvais. Sauf si vous spécifiez le rootparamètre de répertoire, comme vu ici: github.com/visionmedia/express/issues/1465
Joe
2
var chemin = require ('chemin');
Matt Harrison
1
ouais le code final !!
SuperUberDuper
2
La mise à jour @MattHarrison ES6, pour les importations de packages, constest préférable àvar
Nino Filiu
39

Cette réponse rassemble les informations des autres réponses / commentaires.

Cela dépend si vous souhaitez inclure quelque chose relatif au répertoire de travail du processus (cwd) ou au répertoire de fichiers. Les deux utilisent la path.resolvefonction (placée var path = require('path')en haut du fichier.

  • par rapport à cwd: path.resolve('../../some/path/to/file.txt');
  • par rapport au fichier: path.resolve(__dirname+'../../some/path/to/file.txt');

En lisant le lien du commentaire de @ Joe, il semble que les chemins relatifs représentent un risque pour la sécurité si vous acceptez l'entrée de l'utilisateur pour le chemin (par exemple, cela sendfile('../.ssh/id_rsa')pourrait être le premier essai d'un pirate informatique).

derekdreery
la source
1
En tant que débutant, je veux savoir comment le scénario de hacker est arrivé ici?
bharath muppa du
2
Si vous autorisez accidentellement l'utilisateur à entrer le chemin du fichier qu'il souhaite télécharger, il pourrait télécharger n'importe quel fichier sur votre système (j'ai donné l'exemple d'une clé privée ssh - ce qui lui donnerait la possibilité de se faire passer pour votre PC ( man-in-the-middle etc)). La restriction .. interdit cette possibilité car seuls les fichiers du site Web sont accessibles.
derekdreery
30

La documentation Express suggère de le faire d'une manière différente, et à mon avis, cela a plus de sens plus tard que la solution actuelle.

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

L'option racine semble être définie ./comme répertoire racine de votre projet. Je ne peux donc pas dire complètement où se trouve votre fichier par rapport à la racine du projet, mais si votre dossier temporaire s'y trouve, vous pouvez définir ./tempcomme racine du fichier que vous envoyez.

ténor528
la source
1
C'est vrai, mais il utilise sendFile (F majuscule, pris en charge par Express v4.8.0 et les versions ultérieures) au lieu de l'ancien sendfile utilisé par l'OP. Juste en disant ... =]
RemyNL
Ahh ... bonne prise. Je n'ai pas remarqué cette petite différence. Je me demande également si la réponse sélectionnée fonctionne non pas parce qu'elle utilise .sendfilemais parce qu'elle repose complètement sur autre chose (chemin). Merci de l'avoir signalé.
ténor528
Simple et efficace. Je vous remercie! Cela a parfaitement fonctionné pour moi!
Emanuela Colta