From ba07a4e9754391ad2b13ef0863985babefbad8ef Mon Sep 17 00:00:00 2001 From: Artem Derevnjuk Date: Sat, 18 Jan 2025 17:44:09 +0400 Subject: [PATCH 1/3] chore: empty commit for PR From 1931f76def13c2b578e08fc8e735c1a6ece861cf Mon Sep 17 00:00:00 2001 From: Artem Derevnjuk Date: Sat, 18 Jan 2025 17:47:54 +0400 Subject: [PATCH 2/3] test: add Bright's tests --- ...rticles-example-article-comments-1.test.js | 40 +++++++++++++ .../sec/delete-articles-slug-favorite.test.js | 40 +++++++++++++ test/sec/delete-articles-slug.test.js | 44 ++++++++++++++ .../delete-profiles-johndoe-follow.test.js | 46 ++++++++++++++ test/sec/get-api-user.test.js | 44 ++++++++++++++ ...-articles-example-article-comments.test.js | 44 ++++++++++++++ test/sec/get-articles-feed.test.js | 45 ++++++++++++++ test/sec/get-articles-slug.test.js | 48 +++++++++++++++ test/sec/get-articles.test.js | 49 +++++++++++++++ test/sec/get-profiles-johndoe.test.js | 45 ++++++++++++++ test/sec/get-tags.js | 43 +++++++++++++ test/sec/post-api-users-login.test.js | 58 ++++++++++++++++++ test/sec/post-api-users.test.js | 60 +++++++++++++++++++ ...-articles-example-article-comments.test.js | 59 ++++++++++++++++++ test/sec/post-articles-slug-favorite.test.js | 45 ++++++++++++++ test/sec/post-articles.test.js | 52 ++++++++++++++++ test/sec/post-profiles-johndoe-follow.test.js | 47 +++++++++++++++ test/sec/post-sentiment-score.test.js | 45 ++++++++++++++ test/sec/put-api-user.test.js | 60 +++++++++++++++++++ test/sec/put-articles-slug.test.js | 51 ++++++++++++++++ 20 files changed, 965 insertions(+) create mode 100644 test/sec/delete-articles-example-article-comments-1.test.js create mode 100644 test/sec/delete-articles-slug-favorite.test.js create mode 100644 test/sec/delete-articles-slug.test.js create mode 100644 test/sec/delete-profiles-johndoe-follow.test.js create mode 100644 test/sec/get-api-user.test.js create mode 100644 test/sec/get-articles-example-article-comments.test.js create mode 100644 test/sec/get-articles-feed.test.js create mode 100644 test/sec/get-articles-slug.test.js create mode 100644 test/sec/get-articles.test.js create mode 100644 test/sec/get-profiles-johndoe.test.js create mode 100644 test/sec/get-tags.js create mode 100644 test/sec/post-api-users-login.test.js create mode 100644 test/sec/post-api-users.test.js create mode 100644 test/sec/post-articles-example-article-comments.test.js create mode 100644 test/sec/post-articles-slug-favorite.test.js create mode 100644 test/sec/post-articles.test.js create mode 100644 test/sec/post-profiles-johndoe-follow.test.js create mode 100644 test/sec/post-sentiment-score.test.js create mode 100644 test/sec/put-api-user.test.js create mode 100644 test/sec/put-articles-slug.test.js diff --git a/test/sec/delete-articles-example-article-comments-1.test.js b/test/sec/delete-articles-example-article-comments-1.test.js new file mode 100644 index 0000000..14274b1 --- /dev/null +++ b/test/sec/delete-articles-example-article-comments-1.test.js @@ -0,0 +1,40 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('DELETE /articles/example-article/comments/1', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + await runner.createScan({ + tests: [TestType.BROKEN_ACCESS_CONTROL, TestType.JWT, 'id_enumeration'], + attackParamLocations: [AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'DELETE', + url: 'http://localhost:3000/articles/example-article/comments/1', + headers: { 'Authorization': 'Token required_jwt_token' } + }) + + t.end() +}) diff --git a/test/sec/delete-articles-slug-favorite.test.js b/test/sec/delete-articles-slug-favorite.test.js new file mode 100644 index 0000000..0fd625c --- /dev/null +++ b/test/sec/delete-articles-slug-favorite.test.js @@ -0,0 +1,40 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('DELETE /articles/:slug/favorite', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + await runner.createScan({ + tests: [TestType.JWT, TestType.BROKEN_ACCESS_CONTROL, 'CSRF', TestType.HTTP_METHOD_FUZZING], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'DELETE', + url: `${server.baseUrl}/articles/:slug/favorite`, + headers: { 'Authorization': 'Token jwt.token.here' } + }) + + t.end() +}) diff --git a/test/sec/delete-articles-slug.test.js b/test/sec/delete-articles-slug.test.js new file mode 100644 index 0000000..4b2b0f2 --- /dev/null +++ b/test/sec/delete-articles-slug.test.js @@ -0,0 +1,44 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('DELETE /articles/:slug', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('Security tests', async t => { + await runner.createScan({ + tests: [TestType.BROKEN_ACCESS_CONTROL, TestType.JWT, 'csrf', TestType.SQLI], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'DELETE', + url: `${server.baseUrl}/articles/:slug`, + headers: { 'Authorization': 'Token jwt.token.here' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/delete-profiles-johndoe-follow.test.js b/test/sec/delete-profiles-johndoe-follow.test.js new file mode 100644 index 0000000..5205206 --- /dev/null +++ b/test/sec/delete-profiles-johndoe-follow.test.js @@ -0,0 +1,46 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('DELETE /profiles/johndoe/follow', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('Security tests', async t => { + await runner.createScan({ + tests: [TestType.JWT, TestType.BROKEN_ACCESS_CONTROL, 'csrf'], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.BODY] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'DELETE', + url: `${server.baseUrl}/profiles/johndoe/follow`, + headers: { + Authorization: 'Token required_jwt_token' + } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-api-user.test.js b/test/sec/get-api-user.test.js new file mode 100644 index 0000000..7929dd1 --- /dev/null +++ b/test/sec/get-api-user.test.js @@ -0,0 +1,44 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /api/user', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /api/user', async t => { + await runner.createScan({ + tests: [TestType.BROKEN_ACCESS_CONTROL, TestType.JWT, 'EXCESSIVE_DATA_EXPOSURE'], + attackParamLocations: [AttackParamLocation.HEADER] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: 'http://localhost:3000/api/user', + headers: { 'Authorization': 'Bearer ' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-articles-example-article-comments.test.js b/test/sec/get-articles-example-article-comments.test.js new file mode 100644 index 0000000..60bad3f --- /dev/null +++ b/test/sec/get-articles-example-article-comments.test.js @@ -0,0 +1,44 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /articles/example-article/comments', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /articles/example-article/comments', async t => { + await runner.createScan({ + tests: [TestType.JWT, 'excessive_data_exposure', 'broken_access_control'], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: 'http://localhost:3000/articles/example-article/comments', + headers: { 'Authorization': 'Token optional_jwt_token' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-articles-feed.test.js b/test/sec/get-articles-feed.test.js new file mode 100644 index 0000000..f1db25a --- /dev/null +++ b/test/sec/get-articles-feed.test.js @@ -0,0 +1,45 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /articles/feed', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /articles/feed', async t => { + await runner.createScan({ + tests: [TestType.JWT, 'excessive_data_exposure', 'broken_access_control', TestType.HTTP_METHOD_FUZZING], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: '/articles/feed', + headers: { 'Authorization': 'Token jwt.token.here' }, + queryString: { limit: 'number', offset: 'number' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-articles-slug.test.js b/test/sec/get-articles-slug.test.js new file mode 100644 index 0000000..423fdc0 --- /dev/null +++ b/test/sec/get-articles-slug.test.js @@ -0,0 +1,48 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /articles/:slug', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /articles/:slug', async t => { + await runner.createScan({ + tests: [ + TestType.BROKEN_ACCESS_CONTROL, + TestType.EXCESSIVE_DATA_EXPOSURE, + 'id_enumeration', + TestType.XSS + ], + attackParamLocations: [AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: `${server.baseUrl}/articles/test-slug` + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-articles.test.js b/test/sec/get-articles.test.js new file mode 100644 index 0000000..3c15f69 --- /dev/null +++ b/test/sec/get-articles.test.js @@ -0,0 +1,49 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /articles', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /articles', async t => { + await runner.createScan({ + tests: [TestType.SQLI, TestType.XSS, 'excessive_data_exposure', 'http_method_fuzzing', 'mass_assignment'], + attackParamLocations: ['query'] + }) + .threshold('medium') + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: '/articles', + query: { + tag: 'string', + author: 'string', + favorited: 'string', + limit: 10, + offset: 0 + } + }) + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-profiles-johndoe.test.js b/test/sec/get-profiles-johndoe.test.js new file mode 100644 index 0000000..4127eb2 --- /dev/null +++ b/test/sec/get-profiles-johndoe.test.js @@ -0,0 +1,45 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /profiles/johndoe', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('GET /profiles/johndoe', async t => { + await runner + .createScan({ + tests: [TestType.BROKEN_ACCESS_CONTROL, TestType.JWT, 'EXCESSIVE_DATA_EXPOSURE'], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: '/profiles/johndoe', + headers: { 'Authorization': 'Token optional_jwt_token' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/get-tags.js b/test/sec/get-tags.js new file mode 100644 index 0000000..8055b4c --- /dev/null +++ b/test/sec/get-tags.js @@ -0,0 +1,43 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for GET /api/tags', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('Excessive Data Exposure and HTTP Method Fuzzing', async t => { + await runner.createScan({ + tests: [TestType.EXCESSIVE_DATA_EXPOSURE, 'HTTP_METHOD_FUZZING'], + attackParamLocations: [] + }) + .threshold('MEDIUM') + .timeout(15 * 60 * 1000) + .run({ + method: 'GET', + url: `${server.baseUrl}/api/tags` + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-api-users-login.test.js b/test/sec/post-api-users-login.test.js new file mode 100644 index 0000000..af827aa --- /dev/null +++ b/test/sec/post-api-users-login.test.js @@ -0,0 +1,58 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /api/users/login', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('Run security tests', async t => { + await runner.createScan({ + tests: [ + TestType.BRUTE_FORCE_LOGIN, + TestType.CSRF, + TestType.SQLI, + TestType.XSS, + 'insecure_output_handling' + ], + attackParamLocations: ['body'] + }) + .threshold('medium') + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: 'http://localhost:3000/api/users/login', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + user: { + email: 'user@example.com', + password: 'password123' + } + }) + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-api-users.test.js b/test/sec/post-api-users.test.js new file mode 100644 index 0000000..8ae464d --- /dev/null +++ b/test/sec/post-api-users.test.js @@ -0,0 +1,60 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /api/users', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /api/users', async t => { + await runner.createScan({ + tests: [ + TestType.CSRF, + TestType.BRUTE_FORCE_LOGIN, + TestType.MASS_ASSIGNMENT, + TestType.SQLI, + TestType.XSS, + 'EMAIL_INJECTION' + ], + attackParamLocations: ['BODY'] + }) + .threshold('MEDIUM') + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: 'http://localhost:3000/api/users', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + user: { + username: 'newuser', + email: 'newuser@example.com', + password: 'password123' + } + }) + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-articles-example-article-comments.test.js b/test/sec/post-articles-example-article-comments.test.js new file mode 100644 index 0000000..f95722e --- /dev/null +++ b/test/sec/post-articles-example-article-comments.test.js @@ -0,0 +1,59 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /articles/example-article/comments', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /articles/example-article/comments', async t => { + await runner.createScan({ + tests: [ + TestType.JWT, + TestType.CSRF, + TestType.XSS, + TestType.SQLI, + 'excessive_data_exposure', + 'broken_access_control' + ], + attackParamLocations: [AttackParamLocation.BODY, AttackParamLocation.HEADER] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: 'http://localhost:3000/articles/example-article/comments', + headers: { + 'Authorization': 'Token required_jwt_token', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + comment: { + body: 'This is a comment.' + } + }) + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-articles-slug-favorite.test.js b/test/sec/post-articles-slug-favorite.test.js new file mode 100644 index 0000000..d090b79 --- /dev/null +++ b/test/sec/post-articles-slug-favorite.test.js @@ -0,0 +1,45 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /articles/:slug/favorite', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /articles/:slug/favorite', async t => { + await runner.createScan({ + tests: [TestType.JWT, 'csrf', TestType.BROKEN_ACCESS_CONTROL, 'http_method_fuzzing', TestType.XSS], + attackParamLocations: [AttackParamLocation.BODY, AttackParamLocation.HEADER] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: `${server.baseUrl}/articles/:slug/favorite`, + headers: { 'Authorization': 'Token jwt.token.here' }, + body: {} + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-articles.test.js b/test/sec/post-articles.test.js new file mode 100644 index 0000000..b4fe6cd --- /dev/null +++ b/test/sec/post-articles.test.js @@ -0,0 +1,52 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /articles', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /articles', async t => { + await runner.createScan({ + tests: [TestType.JWT, TestType.CSRF, TestType.MASS_ASSIGNMENT, TestType.XSS, TestType.SQLI], + attackParamLocations: [AttackParamLocation.BODY, AttackParamLocation.HEADER] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: `${server.baseUrl}/articles`, + headers: { 'Authorization': 'Token jwt.token.here' }, + body: JSON.stringify({ + article: { + title: 'string', + description: 'string', + body: 'string', + tagList: ['string'] + } + }) + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-profiles-johndoe-follow.test.js b/test/sec/post-profiles-johndoe-follow.test.js new file mode 100644 index 0000000..2bf9399 --- /dev/null +++ b/test/sec/post-profiles-johndoe-follow.test.js @@ -0,0 +1,47 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /profiles/johndoe/follow', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /profiles/johndoe/follow', async t => { + await runner.createScan({ + tests: [TestType.JWT, TestType.CSRF, TestType.BROKEN_ACCESS_CONTROL, 'business_constraint_bypass'], + attackParamLocations: [AttackParamLocation.HEADER, AttackParamLocation.BODY] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: `${server.baseUrl}/profiles/johndoe/follow`, + headers: { + 'Authorization': 'Token required_jwt_token' + }, + body: {} + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/post-sentiment-score.test.js b/test/sec/post-sentiment-score.test.js new file mode 100644 index 0000000..5e89b92 --- /dev/null +++ b/test/sec/post-sentiment-score.test.js @@ -0,0 +1,45 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for POST /sentiment/score', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('POST /sentiment/score', async t => { + await runner.createScan({ + tests: [TestType.JWT, TestType.CSRF, TestType.EXCESSIVE_DATA_EXPOSURE, TestType.XSS], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'POST', + url: `${server.baseUrl}/sentiment/score`, + headers: { 'Authorization': 'Bearer ' }, + body: { 'content': '' } + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/put-api-user.test.js b/test/sec/put-api-user.test.js new file mode 100644 index 0000000..aeb7386 --- /dev/null +++ b/test/sec/put-api-user.test.js @@ -0,0 +1,60 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('Security tests for PUT /api/user', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('PUT /api/user', async t => { + await runner.createScan({ + tests: [ + TestType.BROKEN_ACCESS_CONTROL, + TestType.CSRF, + TestType.EXCESSIVE_DATA_EXPOSURE, + TestType.MASS_ASSIGNMENT, + TestType.SQLI, + TestType.XSS + ], + attackParamLocations: ['BODY', 'HEADER'] + }) + .threshold('MEDIUM') + .timeout(15 * 60 * 1000) + .run({ + method: 'PUT', + url: 'http://localhost:3000/api/user', + headers: { + 'Authorization': 'Bearer ', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + user: { + email: 'updateduser@example.com', + password: 'newpassword123' + } + }) + }) + + t.end() + }) + + t.end() +}) diff --git a/test/sec/put-articles-slug.test.js b/test/sec/put-articles-slug.test.js new file mode 100644 index 0000000..c6d80a5 --- /dev/null +++ b/test/sec/put-articles-slug.test.js @@ -0,0 +1,51 @@ +'use strict' +const t = require('tap') +const startServer = require('../setup-server') +const { SecRunner, TestType, AttackParamLocation, Severity } = require('@sectester/runner') + +let runner + +// Increase the timeout for the tests +jest.setTimeout(15 * 60 * 1000) // 15 minutes + +t.test('PUT /articles/:slug', async t => { + let server + + t.beforeEach(async () => { + server = await startServer() + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME + }) + await runner.init() + }) + + t.teardown(async () => { + await runner.clear() + await server.close() + }) + + t.test('Security tests', async t => { + await runner.createScan({ + tests: [TestType.JWT, TestType.CSRF, TestType.MASS_ASSIGNMENT, TestType.XSS, TestType.SQLI], + attackParamLocations: [AttackParamLocation.BODY, AttackParamLocation.HEADER, AttackParamLocation.PATH] + }) + .threshold(Severity.MEDIUM) + .timeout(15 * 60 * 1000) + .run({ + method: 'PUT', + url: `${server.baseUrl}/articles/:slug`, + headers: { 'Authorization': 'Token jwt.token.here' }, + body: JSON.stringify({ + article: { + title: 'string', + description: 'string', + body: 'string' + } + }) + }) + + t.end() + }) + + t.end() +}) From da5137e9d8b76b8aa1af3f9b9f4b79aff854fde7 Mon Sep 17 00:00:00 2001 From: Artem Derevnjuk Date: Sat, 18 Jan 2025 17:48:03 +0400 Subject: [PATCH 3/3] test: add Bright's workflow file --- .github/workflows/bright.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/bright.yml diff --git a/.github/workflows/bright.yml b/.github/workflows/bright.yml new file mode 100644 index 0000000..173aad2 --- /dev/null +++ b/.github/workflows/bright.yml @@ -0,0 +1,29 @@ +name: CI + +on: + pull_request: + branches: + - '**' + +jobs: + test: + runs-on: ubuntu-latest + + env: + BRIGHT_HOSTNAME: ${{ vars.BRIGHT_HOSTNAME }} + BRIGHT_TOKEN: ${{ secrets.BRIGHT_TOKEN }} + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' + + - name: Install dependencies + run: npm install + + - name: Run tests + run: npm test -- test/sec/*