API Schema: scanning, configuring
To scan API entrypoints, upload an API schema file to Bright. For a scan to be successful, please make sure that you are using a valid schema that is configured in compliance with the original specification (OpenAPI/ Swagger or Postman, respectively).
Scan API Entrypoints using a schema
To scan API entrypoints using a predefined schema, follow these steps:
- In the Targets tab, scroll to the Discover Entrypoints section, and select For APIs to use either an Open API specification (Swagger) or a Postman collection:
*.yml
/*.yaml
/*.json
.
Bright supports the following versions of the API schemas: Swagger 2+, OpenAPI 3+, Postman 2+. To ensure proper scanning of an API, you must configure the schema according to the general specification and specific Bright requirements. Find more information about the configuration validation here.
- Select a schema file for the scan. You can either upload the file from a disk or use a pre-uploaded file. Also, you can import a schema from a cloud by specifying the relative URL.
Once you upload the schema file, you can open it in the Schema Editor. Use this option to validate and edit the uploaded schema before running a scan. Some schema files may contain configuration errors that block scanning. To learn how to identify the files with configuration errors, see Configuring an API Schema.
Sample file
This is the sample .json file with defined Default Values, made for BrokenCrystals:
{
"openapi": "3.0.0",
"info": {
"title": "Broken Crystals",
"description": "\n ![BC logo](/assets/img/logo_blue_small.png)\n\n This is the _Broken Crystals_ REST API.\n\n _Broken Crystals_ is a benchmark application that uses modern technologies and implements a set of common security vulnerabilities.\n\n ## Available endpoints\n\n * [App](#/App%20controller) - common operations\n\n * [Auth](#/Auth%20controller) - operations with authentication methods\n\n * [User](#/User%20controller) - operations with users(creation, searching)\n\n * [Files](#/Files%20controller) - operations with files\n\n * [Subscriptions](#/Subscriptions%20controller) - operations with subscriptions\n\n * [Testimonials](#/Testimonials%20controller) - operations with testimonials\n\n * [Products](#/Products%20controller) — operations with products\n\n\n ",
"version": "1.0",
"contact": {}
},
"tags": [],
"servers": [
{
"url": "https://brokencrystals.com"
}
],
"components": {
"schemas": {
"AppConfig": {
"type": "object",
"properties": {
"awsBucket": {
"type": "string"
},
"sql": {
"type": "string"
},
"googlemaps": {
"type": "string"
}
},
"required": [
"awsBucket",
"sql",
"googlemaps"
]
},
"LoginRequest": {
"type": "object",
"properties": {
"user": {
"type": "string"
},
"password": {
"type": "string"
},
"op": {
"type": "string",
"enum": [
"basic",
"html",
"csrf",
"csrf_dom",
"oidc"
]
}
},
"required": [
"user",
"password",
"op"
]
},
"LoginResponse": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"ldapProfileLink": {
"type": "string",
"description": "ldap query link for user details"
}
},
"required": [
"email",
"ldapProfileLink"
]
},
"OidcClientResponse": {
"type": "object",
"properties": {
"clientId": {
"type": "string"
},
"clientSecret": {
"type": "string"
},
"metadataUrl": {
"type": "string"
}
},
"required": [
"clientId",
"clientSecret",
"metadataUrl"
]
},
"LoginJwtResponse": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"email": {
"type": "string"
},
"ldapProfileLink": {
"type": "string",
"description": "ldap query link for user details"
}
},
"required": [
"token",
"email",
"ldapProfileLink"
]
},
"JwtValidationResponse": {
"type": "object",
"properties": {
"secret": {
"type": "string"
}
},
"required": [
"secret"
]
},
"UserDto": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
},
"required": [
"email",
"firstName",
"lastName"
]
},
"CreateUserRequest": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"password": {
"type": "string"
}
},
"required": [
"email",
"firstName",
"lastName",
"password"
]
},
"CreateTestimonialRequest": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"title": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"name",
"title",
"message"
]
},
"TestimonialDto": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"title": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"name",
"title",
"message"
]
},
"ProductDto": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"category": {
"type": "string"
},
"photoUrl": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"name",
"category",
"photoUrl",
"description"
]
}
}
},
"paths": {
"/api/render": {
"post": {
"operationId": "AppController_renderTemplate",
"summary": "",
"description": "Template for rendering by doT. Expects plain text as request body",
"parameters": [],
"requestBody": {
"required": true,
"description": "Write your text here",
"content": {
"text/plain": {
"schema": {
"type": "string"
},
"example": "This is a value"
}
}
},
"responses": {
"201": {
"description": "Rendered result"
}
},
"tags": [
"App controller"
]
}
},
"/api/goto": {
"get": {
"operationId": "AppController_redirect",
"summary": "",
"description": "Redirects the user to the provided url",
"parameters": [
{
"name": "url",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "https://brokencrystals.com/api/users/basic"
}
],
"responses": {
"200": {
"description": "Redirected"
}
},
"tags": [
"App controller"
]
}
},
"/api/metadata": {
"post": {
"operationId": "AppController_xml",
"summary": "",
"description": "Receives client's metadata in XML format. Returns the passed XML",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "string"
},
"example": "<note>\n<to>Tove</to>\n<from>Jani</from>\n<heading>Reminder</heading>\n<body>Don't forget me this weekend!</body>\n</note>"
}
}
},
"responses": {
"201": {
"description": "XML passed successfully"
},
"500": {
"description": "Invalid data"
}
},
"tags": [
"App controller"
]
}
},
"/api": {
"options": {
"operationId": "AppController_getTestOptions",
"summary": "",
"description": "Returns the list of supported operations",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"tags": [
"App controller"
]
}
},
"/api/spawn": {
"get": {
"operationId": "AppController_launchCommand",
"summary": "",
"description": "Launches system command on server",
"parameters": [
{
"name": "command",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "ls /var/www/*"
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"500": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"App controller"
]
}
},
"/api/config": {
"get": {
"operationId": "AppController_getConfig",
"summary": "",
"description": "Returns server configuration to the client",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AppConfig"
}
}
}
}
},
"tags": [
"App controller"
]
}
},
"/api/auth/admin/login": {
"post": {
"operationId": "AuthController_loginWithRSAJwtKeysAdmin",
"summary": "",
"description": "Authenticates user and returns JWT token with RSA256 protocol. The key is siigned with RSA private key.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/login": {
"post": {
"operationId": "AuthController_loginWithRSAJwtKeys",
"summary": "",
"description": "Authenticates user and returns JWT token with RSA256 protocol. The key is siigned with RSA private key.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/dom-csrf-flow": {
"get": {
"operationId": "AuthController_getDomCsrfToken",
"summary": "",
"description": "Authenticates user and returns DOM CSRF token.",
"parameters": [],
"responses": {
"400": {
"description": "Bad request, fingerprint is required",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/simple-csrf-flow": {
"get": {
"operationId": "AuthController_getCsrfToken",
"summary": "",
"description": "Returns Simple CSRF token.",
"parameters": [],
"responses": {
"200": {
"description": "Returns simple csrf token"
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/oidc-client": {
"get": {
"operationId": "AuthController_getOidcClient",
"summary": "",
"description": "Get OIDC client configuration. Returns public OIDC. These keys are configurable via CLIENT_ID, CLIENT_SECRET env variables.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OidcClientResponse"
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/kid-sql/login": {
"post": {
"operationId": "AuthController_loginWithKIDSqlJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key id is provided in KID protocol.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/kid-sql/validate": {
"get": {
"operationId": "AuthController_validateWithKIDSqlJwt",
"summary": "",
"description": "Validates the JWT header and returns secret if the header is valid. Executes SQL query by concatenating the KID value with the query.\n In case of None algorithm ignores the signature.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/weak-key/login": {
"post": {
"operationId": "AuthController_loginWithWeakKeyJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key is configurable on server via the JWT_SECRET_KEY env variable.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/weak-key/validate": {
"get": {
"operationId": "AuthController_validateWithWeakKeyJwt",
"summary": "",
"description": "Validates the JWT header and return secret if the header is valid. The token validation is done using algorithm in header and key\n that is configured in JWT_SECRET_KEY env variable. In case of None algorithm ignores the signature.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/jku/login": {
"post": {
"operationId": "AuthController_loginWithJKUJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key is configurable on server via the JWT_SECRET_KEY env variable.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/jku/validate": {
"get": {
"operationId": "AuthController_validateWithJKUJwt",
"summary": "",
"description": "Vulnerability case: Uses publicly available JSON to check if JWT is properly signed after the Header in JWT is set to point to our JSON and sign the JWT with our private key.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/jwk/login": {
"post": {
"operationId": "AuthController_loginWithJWKJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key is configurable on server via JWT_SECRET_KEY env variable.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/jwk/validate": {
"get": {
"operationId": "AuthController_validateWithJWKJwt",
"summary": "",
"description": "Vulrenability case: JWK field JSON in Header has empty values and our private key to sign the JWT",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/x5c/login": {
"post": {
"operationId": "AuthController_loginWithX5CJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key is configurable on server via the JWT_SECRET_KEY env variable.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/x5c/validate": {
"get": {
"operationId": "AuthController_validateWithX5CJwt",
"summary": "",
"description": "Vulnerability case: The application doesn’t properly check which X5C key is used for signing and when X5C headers are set to our values and signed with our private key, authentication is bypassed.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/x5u/login": {
"post": {
"operationId": "AuthController_loginWithX5UJwt",
"summary": "",
"description": "Authenticates user and returns JWT token with HCA256. The key is configurable on server via the JWT_SECRET_KEY env variable.",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
},
"example": "{\n \"user\": \"admin\",\n \"password\": \"admin\",\n \"op\": \"basic\"\n}"
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginJwtResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/auth/jwt/x5u/validate": {
"get": {
"operationId": "AuthController_validateWithX5UJwt",
"summary": "",
"description": "Vulnerability case: Uses the uploaded certificate to sign the JWT and sets the X5U Header in JWT to point to the uploaded certificate.",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/JwtValidationResponse"
}
}
}
},
"401": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth controller"
]
}
},
"/api/users": {
"options": {
"operationId": "UsersController_getTestOptions",
"summary": "",
"description": "List of permitted communication options",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"tags": [
"User controller"
]
}
},
"/api/users/one/{email}": {
"get": {
"operationId": "UsersController_getUser",
"summary": "",
"description": "Returns user by email",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"200": {
"description": "Returns user object if it exists",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserDto"
}
}
}
},
"404": {
"description": "User not founded",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/users/{id}": {
"get": {
"operationId": "UsersController_getUserById",
"summary": "",
"description": "Returns user by id",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "number"
},
"example": "1"
}
],
"responses": {
"200": {
"description": "Returns user object if it exists",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserDto"
}
}
}
},
"404": {
"description": "User not founded",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/users/one/{email}/photo": {
"get": {
"operationId": "UsersController_getUserPhoto",
"summary": "",
"description": "Returns user profile photo",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"200": {
"description": "Returns user profile photo"
},
"204": {
"description": "Returns empty content if photo is not set"
},
"403": {
"description": "Returns then user is not authenticated"
}
},
"tags": [
"User controller"
]
},
"put": {
"operationId": "UsersController_uploadFile",
"summary": "",
"description": "Uploads user profile photo",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"200": {
"description": "Photo updated"
}
},
"tags": [
"User controller"
]
}
},
"/api/users/ldap": {
"get": {
"operationId": "UsersController_ldapQuery",
"summary": "",
"description": "Performs LDAP search for user details",
"parameters": [
{
"name": "query",
"required": true,
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserDto"
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/users/basic": {
"post": {
"operationId": "UsersController_createUser",
"summary": "",
"description": "Creates BASIC user in PostGreSQL db",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateUserRequest"
},
"example": "{\n \"email\": \"[email protected]\",\n \"firstName\": \"Jim\",\n \"lastName\": \"Harris\",\n \"password\": \"BC_1234\"\n}"
}
}
},
"responses": {
"201": {
"description": "User created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserDto"
}
}
}
},
"409": {
"description": "User Already exists",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/users/oidc": {
"post": {
"operationId": "UsersController_createOIDCUser",
"summary": "",
"description": "Creates OIDC user in KeyCloak db",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateUserRequest"
},
"example": "{\n \"email\": \"[email protected]\",\n \"firstName\": \"Jim\",\n \"lastName\": \"Harris\",\n \"password\": \"BC_1234\"\n}"
}
}
},
"responses": {
"201": {
"description": "User created, returns empty object"
},
"409": {
"description": "User Already exists",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"errorMessage": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/users/one/{email}/info": {
"put": {
"operationId": "UsersController_changeUserInfo",
"summary": "",
"description": "Method for updating user details. Vulnerability case: Mass Assignment allows an attacker to modify object properties, which are not supposed to be changed by the user",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserDto"
},
"example": "{\n \"name\": \"Jim Harris\",\n \"title\": \"SE\",\n \"message\": \"Lets do this string\"\n}"
}
}
},
"responses": {
"200": {
"description": "Returns updated user"
},
"403": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
},
"get": {
"operationId": "UsersController_getUserInfo",
"summary": "",
"description": "Returns user by email",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"200": {
"description": "Returns user info"
},
"403": {
"description": "invalid credentials",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
},
"404": {
"description": ""
}
},
"tags": [
"User controller"
]
}
},
"/api/users/one/{email}/adminpermission": {
"get": {
"operationId": "UsersController_getAdminStatus",
"summary": "",
"description": "Endpoint for checking admin rights of authenticated user",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"200": {
"description": "Returns true if user has admin rights"
},
"403": {
"description": "user has no admin rights",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"User controller"
]
}
},
"/api/file": {
"get": {
"operationId": "FileController_loadFile",
"summary": "",
"description": "Reads the file from the provided path and the supplied content type and returns the file",
"parameters": [
{
"name": "path",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "/etc/passwd"
},
{
"name": "type",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "text"
},
{
"name": "accept",
"required": true,
"in": "header",
"schema": {
"type": "string"
},
"example": "accept"
}
],
"responses": {
"200": {
"description": "File read successfully"
},
"500": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Files controller"
]
},
"delete": {
"operationId": "FileController_deleteFile",
"summary": "",
"description": "Deletes file at the given path",
"parameters": [
{
"name": "path",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "/home/user/downloads/sample.txt"
}
],
"responses": {
"200": {
"description": "File deleted successfully"
},
"500": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"location": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Files controller"
]
}
},
"/api/file/raw": {
"put": {
"operationId": "FileController_uploadFile",
"summary": "",
"description": "Save raw content on server as a file",
"parameters": [
{
"name": "path",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "/home/user/downloads/sample.txt"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "string"
},
"example": "{\n \"name\": \"string\",\n \"title\": \"string\",\n \"message\": \"string\"\n}"
}
}
},
"responses": {
"200": {
"description": ""
}
},
"tags": [
"Files controller"
]
},
"get": {
"operationId": "FileController_readFile",
"summary": "",
"description": "Read file content on server as a file",
"parameters": [
{
"name": "path",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "/home/user/downloads/sample.txt"
}
],
"responses": {
"200": {
"description": "Returns requested file"
},
"404": {
"description": "File not Found"
}
},
"tags": [
"Files controller"
]
}
},
"/api/subscriptions": {
"post": {
"operationId": "SubscriptionsController_subscribe",
"summary": "",
"description": "Creates subscription for provided email and returns the email address",
"parameters": [
{
"name": "email",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "[email protected]"
}
],
"responses": {
"201": {
"description": "Returns subscribed email"
}
},
"tags": [
"Subscriptions controller"
]
}
},
"/api/testimonials": {
"post": {
"operationId": "TestimonialsController_createTestimonial",
"summary": "",
"description": "Creates testimonial",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTestimonialRequest"
},
"example": "{\n \"name\": \"string\",\n \"title\": \"string\",\n \"message\": \"string\"\n}"
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestimonialDto"
}
}
}
},
"403": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Testimonials controller"
]
},
"get": {
"operationId": "TestimonialsController_getTestimonials",
"summary": "",
"description": "Returns all testimonials",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TestimonialDto"
}
}
}
}
}
},
"tags": [
"Testimonials controller"
]
}
},
"/api/testimonials/count": {
"get": {
"operationId": "TestimonialsController_getCount",
"summary": "",
"description": "Returns count of all testimonials based on provided sql query",
"parameters": [
{
"name": "query",
"required": true,
"in": "query",
"schema": {
"type": "string"
},
"example": "vulnerability"
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
},
"tags": [
"Testimonials controller"
]
}
},
"/api/products": {
"get": {
"operationId": "ProductsController_getProducts",
"summary": "",
"description": "Returns all products",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProductDto"
}
}
}
}
},
"403": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"statusCode": {
"type": "number"
},
"message": {
"type": "string"
},
"error": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Products controller"
]
}
},
"/api/products/latest": {
"get": {
"operationId": "ProductsController_getLatestProducts",
"summary": "",
"description": "Returns 3 latest products",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProductDto"
}
}
}
}
}
},
"tags": [
"Products controller"
]
}
}
}
}
-
"variable": [ {"key": "batchResultId", "value": "{{$guid}}"} ]
Configuring an API Schema
IBM API Connect Support now accessible to users, allows for seamless integration with Swagger 2.0 and OpenAPI 3.0 (already supported). With this update, creating scans using the IBM API Connect specification directly exported from API Connect is a breeze, eliminating the need for additional schema conversion.
Bright validates the API schemas you upload for a new scan, either via the Bright storage or directly during the scan setup. If the schema is configured incorrectly (breaks the specification rules), the Bright Schema Editor (Linter) will mark the file as “not ready for scanning”, display an error message and prevent the user from running a scan.
You can easily detect invalid files which cannot be used for a scan by the following indicators:
- If an uploaded file contains an error (for example, a host/server is not specified in the schema, or some parameters are specified incorrectly), then it will be indicated as NOT ready for scanning in the relevant column of the Bright storage.
- The API schemas that are not ready for scanning are also marked with a warning icon (meaning that fixes are required) when selecting a pre-uploaded file during the scan setup.
- If a file that requires fixes is selected during the scan setup, the following warning message appears below API settings: “The selected specification file cannot be used to start a scan. Please use the Schema Editor to fix the issues”.
If an API schema is not ready for scanning, then you should first correct it according to the specifications using the Schema Editor. See Edit an Uploaded API Schema for more information.
The Start scan button will be disabled until you fix all the errors in the schema.
The examples of API schemas that can be properly defined and accepted for scanning by Bright are given below.
Example 1: Swagger.json
{
"swagger": "2.0",
"info": {
"title": "schema",
"description": "My API Schema",
"version": "0.4.5"
},
"host": "brokencrystals.com",
"basePath": "/home",
"schemes": [
"https"
],
"paths": {
"/user/{userEmail}": {
"get": {
"parameters": [
{
"in": "path",
"name": "userEmail",
"required": true,
"type": "string",
"default": "[email protected]"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}
Example 2: Swagger.yaml
swagger: "2.0"
info:
title: schema
description: My API Schema
version: 0.4.5
host: brokencrystals.com
basePath: /home
schemes:
- https
paths:
/user/{userEmail}:
get:
parameters:
- in: path
name: userEmail
required: true
type: "string"
default: "[email protected]"
produces:
- application/json
responses:
200:
description: OK
Example 3: OpenAPI.json
{
"openapi": "3.0.1",
"info": {
"title": "schema",
"description": "My API Schema",
"version": "0.4.5"
},
"servers": [
{
"url": "https://brokencrystals.com/{basePath}",
"variables": {
"basePath": {
"default": "/home"
}
}
}
],
"paths": {
"/user/{userEmail}": {
"post": {
"operationId": "userEmail",
"parameters": [
{
"name": "userEmail",
"in": "path",
"required": true,
"schema": {
"type": "string",
"default": "[email protected]"
}
}
],
"responses": {
"200": {
"description": "200 response",
"content": {
"application/json": {
"schema": {
"$ref": "#"
}
}
}
}
}
}
}
}
}
Example 4: OpenAPI.yaml
openapi: "3.0.1"
info:
title: "schema"
description: "My API Schema"
version: "0.4.5"
servers:
- url: "https://brokencrystals.com/{basePath}"
variables:
basePath:
default: "/home"
paths:
/user/{userEmail}:
post:
operationId: "userEmail"
parameters:
- name: "userEmail"
in: "path"
required: true
schema:
type: "string"
default: "[email protected]"
responses:
"200":
description: "200 response"
content:
application/json:
schema:
$ref: "#"
Example 5: Postman
{
"info": {
"name": "schema",
"description": "My API Schema",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "/user/:userEmail",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/user/:userEmail",
"host": [
"{{baseUrl}}"
],
"path": [
"user",
":userEmail"
],
"variable": [
{
"key": "userEmail",
"value": "docs@brightsec",
"description": "(Required) "
}
]
}
},
"response": [
{
"name": "OK",
"originalRequest": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/user/:userEmail",
"host": [
"{{baseUrl}}"
],
"path": [
"user",
":userEmail"
],
"variable": [
{
"key": "userEmail"
}
]
}
},
"status": "OK",
"code": 200,
"header": [
{
"key": "Content-Type",
"value": "text/plain"
}
],
"cookie": [],
"body": ""
}
]
}
],
"variable": [
{
"key": "baseUrl",
"value": "https://brokencrystals.com/home",
"type": "string"
}
]
}
Editing an API Schema
The Bright Schema Editor is a smart tool for parsing, validating, and editing API schemas to ensure efficient scans. It highlights incorrectly configured endpoints and root nodes with warning and error icons, making issues easy to spot and fix. Error messages include links to the issue's exact location in the schema and a brief description, enabling quick corrections. This helps users meet standard specifications and Bright's requirements, ensuring high-quality scan results.
The Schema Editor supports some features of standard parsers to simplify schema configuration. For example, for repeated nodes in the YAML files, you can identify the first occurrence of the node (object) by an anchor (mark with the ampersand - “&”). Each subsequent occurrence is serialized as an alias node (referenced with an asterisk - “*”) which refers back to this anchor. To get more information, see the YAML specification.
The Schema Editor allows you to view a schema in two modes: a raw schema view and a smart view. The smart view provides a clear breakdown of endpoints and represents all parameters as separate fields. The fields with incorrect or missing values are highlighted and accompanied by a corresponding warning or error message.
Step-by-Step guide
To edit an API schema uploaded for a scan, follow these steps:
- Click Open in schema editor next to the selected file.
-
Fix the configuration issues in the schema based on the error messages displayed at the bottom of the Schema Editor.
You will not be able to start a scan until you fix all the errors indicated with a red icon in the navigation tree and the smart view. The configuration issues that do not prevent running a scan are indicated with a yellow warning icon in the navigation tree and the smart view.
You can find the detailed information about configuration requirements and error types in the Troubleshooting section.
Tips:
- You can easily switch between the error messages using the navigation buttons on the error popup.
- In the smart view, you can filter the endpoints to show only those with problems by selecting the relevant checkbox to the left of the Search bar.
- In the schema view, you can use the following keybindings for easy search and navigation:
- Ctrl-F / Cmd-F: Start searching
- Ctrl-G / Cmd-G: Find next
- Shift-Ctrl-G / Shift-Cmd-G: Find previous
- Shift-Ctrl-F / Cmd-Option-F: Replace
- Shift-Ctrl-R / Shift-Cmd-Option-F: Replace all
- After you fix the configuration issues, click Save & Close to save the changes and proceed with the scan setup.
Updated about 2 months ago