appstage 0.2.17 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +26 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +26 -16
- package/package.json +1 -1
- package/src/controllers/files.ts +38 -27
package/dist/index.cjs
CHANGED
|
@@ -88,23 +88,30 @@ const files = (params) => {
|
|
|
88
88
|
let p = typeof params === "string" ? { base: params } : params;
|
|
89
89
|
let bases = Array.isArray(p.base) ? p.base : [p.base];
|
|
90
90
|
let exts = p.extensions ?? defaultExtensions;
|
|
91
|
-
|
|
91
|
+
let fallthrough = p.fallthrough ?? true;
|
|
92
|
+
return async (req, res, next) => {
|
|
92
93
|
let langs = (p.languages ?? defaultLanguages)(req);
|
|
93
94
|
let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
|
|
94
95
|
if (!matches(path, p.matches)) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
if (fallthrough) next();
|
|
97
|
+
else {
|
|
98
|
+
emitLog(req.app, "Unmatched path", { data: { path } });
|
|
99
|
+
res.status(404).send(await req.app.renderStatus?.(req, res, {
|
|
100
|
+
code: "unmatched_path",
|
|
101
|
+
path
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
100
104
|
return;
|
|
101
105
|
}
|
|
102
106
|
if (path.includes("../")) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
if (fallthrough) next();
|
|
108
|
+
else {
|
|
109
|
+
emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
|
|
110
|
+
res.status(400).send(await req.app.renderStatus?.(req, res, {
|
|
111
|
+
code: "invalid_path",
|
|
112
|
+
path
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
108
115
|
return;
|
|
109
116
|
}
|
|
110
117
|
let filePath = null;
|
|
@@ -121,11 +128,14 @@ const files = (params) => {
|
|
|
121
128
|
for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve(base, path, `index.${exts[i]}`);
|
|
122
129
|
}
|
|
123
130
|
if (filePath === null) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
if (fallthrough) next();
|
|
132
|
+
else {
|
|
133
|
+
emitLog(req.app, "Unknown path", { data: { path } });
|
|
134
|
+
res.status(404).send(await req.app.renderStatus?.(req, res, {
|
|
135
|
+
code: "unknown_path",
|
|
136
|
+
path
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
129
139
|
return;
|
|
130
140
|
}
|
|
131
141
|
if (!p.transform?.length) {
|
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -62,23 +62,30 @@ const files = (params) => {
|
|
|
62
62
|
let p = typeof params === "string" ? { base: params } : params;
|
|
63
63
|
let bases = Array.isArray(p.base) ? p.base : [p.base];
|
|
64
64
|
let exts = p.extensions ?? defaultExtensions;
|
|
65
|
-
|
|
65
|
+
let fallthrough = p.fallthrough ?? true;
|
|
66
|
+
return async (req, res, next) => {
|
|
66
67
|
let langs = (p.languages ?? defaultLanguages)(req);
|
|
67
68
|
let path = typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
|
|
68
69
|
if (!matches(path, p.matches)) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
if (fallthrough) next();
|
|
71
|
+
else {
|
|
72
|
+
emitLog(req.app, "Unmatched path", { data: { path } });
|
|
73
|
+
res.status(404).send(await req.app.renderStatus?.(req, res, {
|
|
74
|
+
code: "unmatched_path",
|
|
75
|
+
path
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
74
78
|
return;
|
|
75
79
|
}
|
|
76
80
|
if (path.includes("../")) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
if (fallthrough) next();
|
|
82
|
+
else {
|
|
83
|
+
emitLog(req.app, "Invalid path (potential traversal attempt)", { data: { path } });
|
|
84
|
+
res.status(400).send(await req.app.renderStatus?.(req, res, {
|
|
85
|
+
code: "invalid_path",
|
|
86
|
+
path
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
82
89
|
return;
|
|
83
90
|
}
|
|
84
91
|
let filePath = null;
|
|
@@ -95,11 +102,14 @@ const files = (params) => {
|
|
|
95
102
|
for (let i = 0; i < exts.length && filePath === null; i++) filePath = await resolve$1(base, path, `index.${exts[i]}`);
|
|
96
103
|
}
|
|
97
104
|
if (filePath === null) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
if (fallthrough) next();
|
|
106
|
+
else {
|
|
107
|
+
emitLog(req.app, "Unknown path", { data: { path } });
|
|
108
|
+
res.status(404).send(await req.app.renderStatus?.(req, res, {
|
|
109
|
+
code: "unknown_path",
|
|
110
|
+
path
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
103
113
|
return;
|
|
104
114
|
}
|
|
105
115
|
if (!p.transform?.length) {
|
package/package.json
CHANGED
package/src/controllers/files.ts
CHANGED
|
@@ -69,6 +69,7 @@ export type FilesParams = {
|
|
|
69
69
|
extensions?: string[];
|
|
70
70
|
languages?: (req: Request) => string[];
|
|
71
71
|
transform?: TransformContent[];
|
|
72
|
+
fallthrough?: boolean;
|
|
72
73
|
};
|
|
73
74
|
|
|
74
75
|
const defaultExtensions = ["html", "htm"];
|
|
@@ -84,37 +85,44 @@ export const files: Controller<string | FilesParams> = (params) => {
|
|
|
84
85
|
|
|
85
86
|
let bases = Array.isArray(p.base) ? p.base : [p.base];
|
|
86
87
|
let exts = p.extensions ?? defaultExtensions;
|
|
88
|
+
let fallthrough = p.fallthrough ?? true;
|
|
87
89
|
|
|
88
|
-
return async (req, res) => {
|
|
90
|
+
return async (req, res, next) => {
|
|
89
91
|
let langs = (p.languages ?? defaultLanguages)(req);
|
|
90
92
|
|
|
91
93
|
let path =
|
|
92
94
|
typeof p.path === "string" ? p.path : (p.path ?? defaultPath)(req);
|
|
93
95
|
|
|
94
96
|
if (!matches(path, p.matches)) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
if (fallthrough) next();
|
|
98
|
+
else {
|
|
99
|
+
emitLog(req.app, "Unmatched path", { data: { path } });
|
|
100
|
+
|
|
101
|
+
res.status(404).send(
|
|
102
|
+
await req.app.renderStatus?.(req, res, {
|
|
103
|
+
code: "unmatched_path",
|
|
104
|
+
path,
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
103
108
|
|
|
104
109
|
return;
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
if (path.includes("../")) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
if (fallthrough) next();
|
|
114
|
+
else {
|
|
115
|
+
emitLog(req.app, "Invalid path (potential traversal attempt)", {
|
|
116
|
+
data: { path },
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
res.status(400).send(
|
|
120
|
+
await req.app.renderStatus?.(req, res, {
|
|
121
|
+
code: "invalid_path",
|
|
122
|
+
path,
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
118
126
|
|
|
119
127
|
return;
|
|
120
128
|
}
|
|
@@ -167,14 +175,17 @@ export const files: Controller<string | FilesParams> = (params) => {
|
|
|
167
175
|
}
|
|
168
176
|
|
|
169
177
|
if (filePath === null) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
if (fallthrough) next();
|
|
179
|
+
else {
|
|
180
|
+
emitLog(req.app, "Unknown path", { data: { path } });
|
|
181
|
+
|
|
182
|
+
res.status(404).send(
|
|
183
|
+
await req.app.renderStatus?.(req, res, {
|
|
184
|
+
code: "unknown_path",
|
|
185
|
+
path,
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
178
189
|
|
|
179
190
|
return;
|
|
180
191
|
}
|