This commit is contained in:
thosakwe 2017-03-28 22:44:56 -04:00
parent fc6bfcb6de
commit 2e441d4bbf
6 changed files with 20 additions and 18 deletions

View file

@ -1,5 +1,5 @@
# security # security
[![version 1.0.1](https://img.shields.io/badge/pub-v1.0.1-brightgreen.svg)](https://pub.dartlang.org/packages/angel_security) [![version 1.0.2](https://img.shields.io/badge/pub-v1.0.2-brightgreen.svg)](https://pub.dartlang.org/packages/angel_security)
[![build status](https://travis-ci.org/angel-dart/security.svg)](https://travis-ci.org/angel-dart/security) [![build status](https://travis-ci.org/angel-dart/security.svg)](https://travis-ci.org/angel-dart/security)
Angel middleware designed to enhance application security by patching common Web security Angel middleware designed to enhance application security by patching common Web security

View file

@ -19,8 +19,12 @@ RequestMiddleware sanitizeHtmlInput(
var sanitizers = {}..addAll(DEFAULT_SANITIZERS)..addAll(replace ?? {}); var sanitizers = {}..addAll(DEFAULT_SANITIZERS)..addAll(replace ?? {});
return (RequestContext req, res) async { return (RequestContext req, res) async {
if (body) _sanitizeMap(await req.lazyBody(), sanitizers); if (body) {
if (query) _sanitizeMap(await req.lazyQuery(), sanitizers); await req.parse();
_sanitizeMap(req.body, sanitizers);
}
if (query) _sanitizeMap(req.query, sanitizers);
return true; return true;
}; };
} }

View file

@ -1,5 +1,5 @@
name: angel_security name: angel_security
version: 1.0.1 version: 1.0.2
description: Angel middleware designed to enhance application security by patching common Web security holes. description: Angel middleware designed to enhance application security by patching common Web security holes.
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
environment: environment:

View file

@ -29,7 +29,7 @@ main() {
..beforeIndexed.listen(hooks.queryWithCurrentUser()) ..beforeIndexed.listen(hooks.queryWithCurrentUser())
..beforeCreated.listen(hooks.hashPassword()); ..beforeCreated.listen(hooks.hashPassword());
app.service('artists') app.service('artists') as HookedService
..beforeIndexed.listen(hooks.restrictToAuthenticated()) ..beforeIndexed.listen(hooks.restrictToAuthenticated())
..beforeRead.listen(hooks.restrictToOwner()) ..beforeRead.listen(hooks.restrictToOwner())
..beforeCreated.listen(hooks.associateCurrentUser()); ..beforeCreated.listen(hooks.associateCurrentUser());

View file

@ -14,10 +14,9 @@ main() async {
TestClient client; TestClient client;
setUp(() async { setUp(() async {
app = new Angel() app = new Angel();
..chain(validate(untrustedSchema)) app.chain([validate(untrustedSchema), sanitizeHtmlInput()])
.chain(sanitizeHtmlInput()) ..post('/untrusted', (RequestContext req, ResponseContext res) async {
.post('/untrusted', (RequestContext req, ResponseContext res) async {
String untrusted = req.body['html']; String untrusted = req.body['html'];
res res
..contentType = ContentType.HTML ..contentType = ContentType.HTML
@ -30,8 +29,7 @@ main() async {
<body>$untrusted</body> <body>$untrusted</body>
</html>'''); </html>''');
}) })
..chain(validate(untrustedSchema)).post('/attribute', ..post('/attribute', (RequestContext req, ResponseContext res) async {
(RequestContext req, ResponseContext res) async {
String untrusted = req.body['html']; String untrusted = req.body['html'];
res res
..contentType = ContentType.HTML ..contentType = ContentType.HTML
@ -108,7 +106,7 @@ main() async {
var response = await client.post('/attribute', body: {'html': xss}); var response = await client.post('/attribute', body: {'html': xss});
print(response.body); print(response.body);
expect(response.body.contains(xss), isFalse); expect(response.body.contains(xss), isFalse);
expect(response.body.toLowerCase().contains('javascript:'), isFalse); expect(response.body.toLowerCase().contains(xss), isFalse);
}); });
test('style attribute', () async { test('style attribute', () async {
@ -116,6 +114,6 @@ main() async {
var response = await client.post('/attribute', body: {'html': xss}); var response = await client.post('/attribute', body: {'html': xss});
print(response.body); print(response.body);
expect(response.body.contains(xss), isFalse); expect(response.body.contains(xss), isFalse);
expect(response.body.toLowerCase().contains('javascript:'), isFalse); expect(response.body.toLowerCase().contains(xss), isFalse);
}); });
} }

View file

@ -27,7 +27,7 @@ main() {
// First request within the hour is fine // First request within the hour is fine
var response = await client.get('/once-per-hour'); var response = await client.get('/once-per-hour');
print(response.body); print(response.body);
expect(response, hasBody('OK')); expect(response, hasBody('"OK"'));
// Second request within an hour? No no no! // Second request within an hour? No no no!
response = await client.get('/once-per-hour'); response = await client.get('/once-per-hour');
@ -39,19 +39,19 @@ main() {
// First request within the minute is fine // First request within the minute is fine
var response = await client.get('/thrice-per-minute'); var response = await client.get('/thrice-per-minute');
print(response.body); print(response.body);
expect(response, hasBody('OK')); expect(response, hasBody('"OK"'));
// Second request within the minute is fine // Second request within the minute is fine
response = await client.get('/thrice-per-minute'); response = await client.get('/thrice-per-minute');
print(response.body); print(response.body);
expect(response.body, hasBody('OK')); expect(response, hasBody('"OK"'));
// Third request within the minute is fine // Third request within the minute is fine
response = await client.get('/thrice-per-minute'); response = await client.get('/thrice-per-minute');
print(response.body); print(response.body);
expect(response, hasBody('OK')); expect(response, hasBody('"OK"'));
// Fourth request within a minute? No no no! // Fourth request within a minute? No no no!
response = await client.get('/thrice-per-minute'); response = await client.get('/thrice-per-minute');