OWASP Juice Shop follows strict conventions for describing challenges. These allow you to easily integrate Juice Shop tutorials, hints and solutions into your own security guides, knowledge bases, testing labs etc.

Challenges API

The endpoint /api/Challenges on your local Juice Shop instance (i.e. http://localhost:3000/api/Challenges) returns information on the configured challenges along with their current state in an easily consumable JSON format:

         "name":"API-only XSS",
         "description":"Perform a <i>persisted</i> XSS attack with <code>&lt;iframe src=\"javascript:alert(`xss`)\"&gt;</code> without using the frontend application at all. <em>(This challenge is <strong>not available</strong> on Heroku!)</em>",
         "hint":"You need to work with the server-side API directly. Try different HTTP verbs on different entities exposed through the API.",
         "name":"Access Log",
         "category":"Sensitive Data Exposure",
         "description":"Gain access to any access log file of the server.",
         "hint":"Who would want a server access log to be accessible through a web application?",

Instead of your own local instance you can also use the API of the publicly available demo instances to pull challenge information:

🚨 There is no uptime guarantee for either of these as they are both only free Heroku dynos. Please refrain from making unnecessary amounts of requests.

API integration example

Challenge declaration file

The single source of truth for challenges in OWASP Juice Shop is its data/static/challenges.yml file. It is used during start-up of the application to populate the Challenges table which is then exposed via the Challenges API endpoint.

Parsing this file directly for integration makes sense when you do not rely on changed settings (e.g. hints being turned off) from an individual Customization and/or you do not have a running Juice Shop instance available in the first place.

  name: 'Some Name'
  category: 'Category of the challenge'
  description: 'Here the actual task for the attacker is described.'
  difficulty: 1 # a number between 1 and 6
  hint: 'A text hint to display on the Score Board when hovering over the challenge'
  hintUrl: '<category>.html#<shortened description>'
  key: someNameChallenge
  disabledEnv: # (optional) to disable challenges dangerous or incompatible in certain environments
    - Docker
    - Heroku
    - Windows
  tutorial: # (optional) present only on challenges with a Hacking Instructor tutorial
    order: 1 # a unique number to specify the recommended order of tutorials

The latest versions of the challenges.yml file can be found here:

Description Link composition Condition Examples

Link to a specific challenge on the legacy Score Board


Will scroll to the challenge, but only if it is visible as per the current filter settings.

http://localhost:3000/#/score-board-legacy?challenge=DOM%20XSS or

Link to a specific challenge on the Score Board

/#/score-board?searchQuery=<name> (or /#/score-board?challenge=<name> as an alias)

Will filter the Score Board resulting in just the one matching challenge.

http://localhost:3000/#/score-board?searchQuery=DOM%20XSS or (or as their aliases http://localhost:3000/#/score-board?challenge=DOM%20XSS and

Link to official hints for a specific challenge

<hintUrl> or

Link to official step-by-step solution for a specific challenge<hash part of hintUrl> or

Direct link to a Hacking Instructor tutorial for a specific challenge


Only for challenges where tutorial is defined.

http://localhost:3000/#/hacking-instructor?challenge=Score%20Board or

YAML integration example

Challenge solution webhook

Any Juice Shop instance can be configured to call a webhook whenever one of its 107 hacking challenges is solved. To use this feature the following environment variable needs to be supplied to the Juice Shop server:

Environment variable Expected value Recommendations


URL of the webhook Juice Shop is supposed to call whenever a challenge is solved.

The webhook URL should be bound to the user who solved the challenge and allow its provider to verify the Juice Shop origin instance. In most cases the webhook URL should be treated as sensitive information and not be published or transmitted unencrypted!

Webhook payload

Juice Shop will send a POST request to the configured SOLUTIONS_WEBHOOK with the following payload:

{ "solution":
  { "challenge": "<'key' of the solved challenge from ./data/static/challenges.yml>",
    "cheatScore": "<probability of 0..1 that this solution has been cheated>",
    "totalCheatScore": "<average probability of 0..1 that solutions up until now have been cheated>",
    "issuedOn": "<yyyy-MM-ddThh:mm:ssZ>"
  "ctfFlag": "<CTF flag code of the solved challenged based on the injected (or default) 'CTF_KEY'>",
  "issuer": {
    "hostName": "<server os hostname>",
    "os": "<server os type (and release)>",
    "appName": "<'' from loaded YAML configuration in ./config folder>",
    "config": "<name of the loaded configuration>",
    "version": "<version from ./package.json>"

Webhook payload example

    "solution": {
        "challenge": "key",
        "cheatScore": 0,
        "totalCheatScore": 0,
        "issuedOn": "2020-12-15T18:24:33.027Z"
    "ctfFlag": "b0d70dce6cadadb85882ea498fac6785dba2349b",
    "issuer": {
        "hostName": "fv-az116-673",
        "os": "Linux (5.4.0-1031-azure)",
        "appName": "OWASP Juice Shop",
        "config": "default",
        "version": "12.3.0-SNAPSHOT"

Vulnerable code snippets API

Any running Juice Shop instance since v12.7.0 provides two REST endpoints /snippets and /snippets/<challengeKey> which can be used to retrieve the actual vulnerable code snippets for many of the challenges. These are described in the REST endpoints section of the Vulnerable code snippets appendix.

API integration example