-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #233 from AikidoSec/patch-url
Only discover endpoints/routes that exist
- Loading branch information
Showing
6 changed files
with
236 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
library/sources/http-server/shouldDiscoverRoute.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import * as t from "tap"; | ||
import { shouldDiscoverRoute } from "./shouldDiscoverRoute"; | ||
|
||
t.test( | ||
"it does not discover route if not found or method not allowed", | ||
async () => { | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 404, route: "/", method: "GET" }), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 405, route: "/", method: "GET" }), | ||
false | ||
); | ||
} | ||
); | ||
|
||
t.test("it discovers route for all other status codes", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 200, route: "/", method: "GET" }), | ||
true | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 500, route: "/", method: "GET" }), | ||
true | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 400, route: "/", method: "GET" }), | ||
true | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 300, route: "/", method: "GET" }), | ||
true | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 201, route: "/", method: "GET" }), | ||
true | ||
); | ||
}); | ||
|
||
t.test("it does not discover route for OPTIONS or HEAD methods", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 200, route: "/", method: "OPTIONS" }), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 200, route: "/", method: "HEAD" }), | ||
false | ||
); | ||
}); | ||
|
||
t.test( | ||
"it does not discover route for OPTIONS or HEAD methods even with other status codes", | ||
async () => { | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 404, route: "/", method: "OPTIONS" }), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ statusCode: 405, route: "/", method: "HEAD" }), | ||
false | ||
); | ||
} | ||
); | ||
|
||
t.test("it does not discover static files", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/service-worker.js", | ||
method: "GET", | ||
}), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/precache-manifest.10faec0bee24db502c8498078126dd53.js", | ||
method: "POST", | ||
}), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/img/icons/favicon-16x16.png", | ||
method: "GET", | ||
}), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/fonts/icomoon.ttf", | ||
method: "GET", | ||
}), | ||
false | ||
); | ||
}); | ||
|
||
t.test("it allows html files", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/index.html", | ||
method: "GET", | ||
}), | ||
false | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/contact.html", | ||
method: "GET", | ||
}), | ||
false | ||
); | ||
}); | ||
|
||
t.test("it allows files with extension of one character", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/a.a", | ||
method: "GET", | ||
}), | ||
true | ||
); | ||
}); | ||
|
||
t.test("it allows files with extension of 5 or more characters", async () => { | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/a.aaaaa", | ||
method: "GET", | ||
}), | ||
true | ||
); | ||
t.same( | ||
shouldDiscoverRoute({ | ||
statusCode: 200, | ||
route: "/a.aaaaaa", | ||
method: "GET", | ||
}), | ||
true | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { extname } from "path"; | ||
|
||
const NOT_FOUND = 404; | ||
const METHOD_NOT_ALLOWED = 405; | ||
const ERROR_CODES = [NOT_FOUND, METHOD_NOT_ALLOWED]; | ||
|
||
export function shouldDiscoverRoute({ | ||
statusCode, | ||
route, | ||
method, | ||
}: { | ||
statusCode: number; | ||
route: string; | ||
method: string; | ||
}) { | ||
const excludedMethods = ["OPTIONS", "HEAD"]; | ||
|
||
if (excludedMethods.includes(method)) { | ||
return false; | ||
} | ||
|
||
if (ERROR_CODES.includes(statusCode)) { | ||
return false; | ||
} | ||
|
||
let extension = extname(route); | ||
|
||
if (extension && extension.startsWith(".")) { | ||
// Remove the dot from the extension | ||
extension = extension.slice(1); | ||
|
||
if (extension.length >= 2 && extension.length <= 4) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} |