mirror of
https://github.com/KeygraphHQ/juice-shop.git
synced 2026-11-12 18:36:21 -10:00
138 lines
4.9 KiB
TypeScript
138 lines
4.9 KiB
TypeScript
/*
|
|
* Copyright (c) 2014-2025 Bjoern Kimminich & the OWASP Juice Shop contributors.
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
import * as frisby from 'frisby'
|
|
import * as security from '../../lib/insecurity'
|
|
const Joi = frisby.Joi
|
|
|
|
const API_URL = 'http://localhost:3000/api'
|
|
const REST_URL = 'http://localhost:3000/rest'
|
|
|
|
const authHeader = { Authorization: 'Bearer ' + security.authorize(), 'content-type': 'application/json' }
|
|
|
|
describe('/api/Challenges', () => {
|
|
it('GET all challenges', () => {
|
|
return frisby.get(API_URL + '/Challenges')
|
|
.expect('status', 200)
|
|
.expect('header', 'content-type', /application\/json/)
|
|
.expect('jsonTypes', 'data.*', {
|
|
id: Joi.number(),
|
|
key: Joi.string(),
|
|
name: Joi.string(),
|
|
description: Joi.string(),
|
|
difficulty: Joi.number(),
|
|
solved: Joi.boolean()
|
|
})
|
|
})
|
|
|
|
it('POST new challenge is forbidden via public API even when authenticated', () => {
|
|
return frisby.post(API_URL + '/Challenges', {
|
|
headers: authHeader,
|
|
body: {
|
|
name: 'Invulnerability',
|
|
description: 'I am not a vulnerability!',
|
|
difficulty: 3,
|
|
solved: false
|
|
}
|
|
})
|
|
.expect('status', 401)
|
|
})
|
|
})
|
|
|
|
describe('/api/Challenges/:id', () => {
|
|
it('GET existing challenge by id is forbidden via public API even when authenticated', () => {
|
|
return frisby.get(API_URL + '/Challenges/1', { headers: authHeader })
|
|
.expect('status', 401)
|
|
})
|
|
|
|
it('PUT update existing challenge is forbidden via public API even when authenticated', () => {
|
|
return frisby.put(API_URL + '/Challenges/1', {
|
|
headers: authHeader,
|
|
body: {
|
|
name: 'Vulnerability',
|
|
description: 'I am a vulnerability!!!',
|
|
difficulty: 3
|
|
}
|
|
})
|
|
.expect('status', 401)
|
|
})
|
|
|
|
it('DELETE existing challenge is forbidden via public API even when authenticated', () => {
|
|
return frisby.del(API_URL + '/Challenges/1', { headers: authHeader })
|
|
.expect('status', 401)
|
|
})
|
|
})
|
|
|
|
describe('/rest/continue-code', () => {
|
|
it('GET can retrieve continue code for currently solved challenges', () => {
|
|
return frisby.get(REST_URL + '/continue-code')
|
|
.expect('status', 200)
|
|
})
|
|
|
|
it('PUT invalid continue code is rejected (alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code/apply/ThisIsDefinitelyNotAValidContinueCode')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT invalid continue code is rejected (non-alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code/apply/%3Cimg%20src=nonexist1%20onerror=alert()%3E')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT continue code for more than one challenge is accepted', () => { // using [1, 2] here
|
|
return frisby.put(REST_URL + '/continue-code/apply/yXjv6Z5jWJnzD6a3YvmwPRXK7roAyzHDde2Og19yEN84plqxkMBbLVQrDeoY')
|
|
.expect('status', 200)
|
|
})
|
|
|
|
it('PUT continue code for non-existent challenge #999 is accepted', () => {
|
|
return frisby.put(REST_URL + '/continue-code/apply/69OxrZ8aJEgxONZyWoz1Dw4BvXmRGkM6Ae9M7k2rK63YpqQLPjnlb5V5LvDj')
|
|
.expect('status', 200)
|
|
})
|
|
})
|
|
|
|
describe('/rest/continue-code-findIt', () => {
|
|
it('GET can retrieve continue code for currently solved challenges', () => {
|
|
return frisby.get(REST_URL + '/continue-code-findIt')
|
|
.expect('status', 200)
|
|
})
|
|
|
|
it('PUT invalid continue code is rejected (alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code-findIt/apply/ThisIsDefinitelyNotAValidContinueCode')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT completely invalid continue code is rejected (non-alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code-findIt/apply/%3Cimg%20src=nonexist1%20onerror=alert()%3E')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT continue code for more than one challenge is accepted', () => { // using [15, 69] here which both have a Coding Challenge
|
|
return frisby.put(REST_URL + '/continue-code-findIt/apply/Xg9oK0VdbW5g1KX9G7JYnqLpz3rAPBh6p4eRlkDM6EaBON2QoPmxjyvwMrP6')
|
|
.expect('status', 200)
|
|
})
|
|
})
|
|
|
|
describe('/rest/continue-code-fixIt', () => {
|
|
it('GET can retrieve continue code for currently solved challenges', () => {
|
|
return frisby.get(REST_URL + '/continue-code-fixIt')
|
|
.expect('status', 200)
|
|
})
|
|
|
|
it('PUT invalid continue code is rejected (alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code-fixIt/apply/ThisIsDefinitelyNotAValidContinueCode')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT completely invalid continue code is rejected (non-alphanumeric)', () => {
|
|
return frisby.put(REST_URL + '/continue-code-fixIt/apply/%3Cimg%20src=nonexist1%20onerror=alert()%3E')
|
|
.expect('status', 404)
|
|
})
|
|
|
|
it('PUT continue code for more than one challenge is accepted', () => { // using [15, 69] here which both have a Coding Challenge
|
|
return frisby.put(REST_URL + '/continue-code-fixIt/apply/y28BEPE2k3yRrdz5p6DGqJONnj41n5UEWawYWgBMoVmL79bKZ8Qve0Xl5QLW')
|
|
.expect('status', 200)
|
|
})
|
|
})
|