Skip to content

Sift Configuration Schema

Sift configuration has 3 main sections:

Configuration parameters that are required are marked as such in the descriptions below. A value for a configuration parameter may contain a template expression - see Configuration Templating for details.

Example Configuration

version: 2
testProfile:
  analyzers:
    - kind: OpenAPIConformance
    - kind: BrokenObjectLevelAuth
    - kind: BUA
    - kind: EmailExposure
    - kind: ServerError
    - kind: PolicyEvaluator
      policy: filename
      rules:
      - rule: nameOfRuleInPolicyFile
        severity: high
    - attacks:
      - file: InjectionStringsFile
        name: faultName
        severity: high
      kind: ConfigurableInjection
    - attacks:
      - file: HeaderInjectionStringsFile
        header: User-Agent
        name: faultName
        severity: high
      kind: ConfigurableHeaderInjection
  defaultGenerators:
    - 11100000-0000-0000-0000-000000000111
    - 22200000-0000-0000-0000-000000000222

targets:
  - id: 00000000-0000-0000-0000-000000000000
    url: http://localhost:8888/
    traceHeader: Sift-Request
    timeout: 5s
    model:
      definition:
        file: examples/VAmPI/openapi3.yaml
        type: API_KIND_OPENAPI
      generators:
        - context: /createApplication
          rules:
            - kind: Regex
              params:
                expr: TL-[0-9]{8}
              pattern: loan_id
              type: string
            - kind: IntRange
              params:
                max: 850
                min: 300
              pattern: fico
              type: number
            - kind: IntRange
              params:
                max: 130
                min: 18
              pattern: age
              type: number
        - context: /createAccessToken/input/body
          rules:
            - kind: IntConstant
              params:
                value: 42
              pattern: expiresAt
              type: number
    authorization:
      user1:
        kind: static
        location: header
        name: Authorization
        value: Bearer eyXXXXXXXXXXXXX
      user2:
        kind: static
        location: header
        name: Authorization
        value: Basic ZGVtbzpwQDU1dzByZAo=
      user3:
        kind: basic
        password: p@55w0rd
        username: demo
      user4:
        command: bearer_token_gen.py
        kind: dynamic
        location: header
        name: Authorization
        timeout: 5m0s
      user5:
        command: http_header_gen.js
        kind: dynamic-http-header
        timeout: 5m0s
    popToken:
      fields:
        - http-method
        - uri
        - body
      header: X-Authorization
      privateKey: ./path/to/popPrivateKey.pem
    operations:
      excludeId:
        - deleteUser
      includeId:
        - createApplication
        - createAccessToken

# Run Parameters (optional)
environmentId: 00000000-0000-0000-0000-000000000000
fuzzLimit: 5
labels:
  env: dev
  commitSHA: c5e902b7ddfd48eace196b0c050f52e069529279
platformUrl: http://localhost:8080
sequenceLimit: 3
timeLimit: 10m25s

Test Profile

testProfile contains configuration parameters that specify what to test in a run.

The testProfile property may contain an object with the sub-properties defined below. Or, it may contain a string that is the filename that contains the Test Profile object.

Analyzers

testProfile.analyzers is a list of Analyzers to use during an analysis run. Each analyzer checks an API for specific kinds of faults. At least one analyzer is required to be specified.

Each item in the list is a map that contains a required key kind, which specifies the kind of analyzer to enable in the analysis. Some analyzers have additional configuration parameters that must be specified in the map. The analyzer descriptions in the Analyzers page contain the configuration name of each kind of analyzer and any additional parameters required by an analyzer.

Default Generators

testProfile.defaultGenerator is an optional list of GeneratorSet IDs that are used as the default generators in a run. Default GeneratorSets define generators for common, global fields. The order of IDs in the list is from highest to lowest precedence. All of the GeneratorSets in the list have lower precedence than generators in the Semantic Model (targets[].model.generators).

Targets

A target is an API that is analyzed by Sift. Each target specifies an API ID that has previously been defined in the Aptori Platform. Other parameters of a target configure the URL at which Sift can access the API, the location of the API definition, and authorization settings for requests to the API.

targets is an array of targets. At least one target is required to be specified. Each target contains:

  • id: Asset ID defined in Aptori Platform. (required)
  • url: Base URL where an application is serving the API. (required)
  • model: Semantic Model of the target API.
    • definition: Location of the API definition. (required)
    • generators: Specify how to generate values for input fields in the API.
    • resourceProfiles: Specify hints for the Semantic Model.
  • authorization: Parameters to configure authorization token for requests.
  • header: Optional additional HTTP header fields to include in requests.
  • operations: Filters for which operations to test.
  • popToken: Parameters to add Proof-of-Possession (PoP) tokens to requests.
  • rateLimit: Control the number of requests per second to invoke.
  • timeout: Request timeout duration.
  • traceHeader: HTTP header field to populate with a unique request identifier.

Model

A Semantic Model describes what the target API looks like and data relationships among its operations. Aptori automatically constructs a Semantic Model from an API definition, but a user may specify hints to refine the Semantic Model.

The targets[].model property may contain an object with the sub-properties defined below. Or, it may contain a string that is a filename that contains the Semantic Model object.

Definition

targets[].model.definition configures a location where Sift can find the API definition. This parameter is required.

Sift can load an API definition from a URL or a file on the local filesystem. Or, Sift can retrieve a specific revision of the API definition from the Platform. Only one of path, file, or revision should be specified. If multiple are specified, then the Sift will choose one according to precedence, from high to low: path, file, revision.

definition has the following fields:

  • type: Type of API definition. Supported types are "API_KIND_OPENAPI".
  • path: Absolute or relative URL to the API definition. If the URL is relative (starts with "/"), then it is resolved relative to the URL of the target API.
  • file: Filename on the local filesystem that contains API definition.
  • revision: Revision ID of an API definition that has been uploaded to the Platform.

Generators

targets[].model.generators is a GeneratorSet that specifies rules for how to select a Generator to produce a value for an input field of an operation. The GeneratorSet may specify both field-specific and wildcard-style rules. Refer to Generators for details.

Specifying a GeneratorSet for an API is optional. When a Generator is not configured for a particular field, Sift intelligently generates values based on its understanding of the API definition.

Resource Profiles

A Resource Profile specifies the kind of resource acted upon and type of action performed by an operation.

targets[].model.resourceProfiles is a list of Resource Profile objects. Each Resource Profile object has the following properties.

  • operation: Operation ID for this ResourceProfile object
  • resource: Name of a kind of resource. Slashes in the string are used to denote hierarchical resources.
  • action: Specifies the type of action the operation performs. One of create, read, update, delete, list.
  • identifier: For action types create and list, this property specifies the field that contains the ID of the resource provided by the operation. The string is formated as a JSON Pointer, such as "/output/body/id" or "/input/path/name".

Authorization

targets[].authorization configures authorization tokens to use in requests sent to a target API. authorization is map of user identity ID to an identity configuration. The user identity ID is a user-specified name for a user identity supplied in requests to the target API.

Each identity configuration contains a required kind property that specifies the kind of authorization for a user identity as one of:

  • static
  • basic
  • dynamic
  • dynamic-http-header

Each kind of authorization has additional configuration parameters, as described in the following subsections.

All of the kinds of authorization may contain an optional validation property. When present, the validation property instructs Sift to validate the authorization credential by making a request to the target and comparing the response status code to an expected value. The validation property is an object with the following properties:

  • method: HTTP method of the validation request
  • path: Path of the validation request is appended to the target's URL.
  • statusCode: Expected status code of the response.

If a validation request fails or the status code does not match, then Sift will abort the run with an error.

Static

A static kind of authorization configures an authorization token value that is valid for the duration of an analysis run. Each static authorization has three required fields:

  • location: The location where the authorization token is passed in a request. This must be set to "header".
  • name: Name of the header key in which the authorization token value is passed in a request. When location is "header", name is the HTTP header key (e.g., "Authorization", "Api-Key").
  • value: The static token value that will be passed in the request.

For example, to set a Bearer JWT in the "Authorization" header, use the following identity configuration, where "{jwt}" is a placeholder for the JWT value.

kind: static
location: header
name: Authorization
value: Bearer {jwt}

This will configure Sift to send the following header in each request:

Authorization: Bearer {jwt}

Basic

A basic kind of authorization configures Sift to use HTTP Basic Authentication as authorization for a request. Each basic authorization has two required fields:

  • username: The username for HTTP Basic authorization.
  • password: The password for HTTP Basic authorization.

For example, the following identity configuration:

kind: basic
username: demo
password: p@55w0rd

will configure Sift to use the following authorization in each request:

Authorization: Basic {base64-encoded("demo:p@55w0rd")}

Dynamic

A dynamic kind of authorization configures Sift to use an authorization value that is provided at runtime by execution of a command and refreshed periodically according to a configured interval. Each dynamic authorization has the following required fields:

  • location: The location where the authorization token is passed in a request. Supported values are: "header".
  • name: Name of the header key in which the authorization token value is passed in a request. When location is "header", the value of name is the HTTP header key (e.g., "Authorization", "Api-Key").
  • command: Command to execute to generate an authorization token.
  • timeout: Interval in seconds at which the command will be executed.

Execution of command must produce a token value on its standard output (stdout). Any leading and trailing whitespace will be trimmed.

Since the command may need to interact with the target application, the URL of the target is set in environment variable "SIFT_TARGET_URL" when the command is executed.

For example, given the following authorization configuration:

kind: dynamic
location: header
name: Authorization
command: echo "Bearer jwt12345"
timeout: 300

Sift will execute command echo "Bearer jwt12345" at least once every 300 seconds, and use the output as the authorization token. In each request, the authorization token will be passed in the following HTTP header specified in the configuration:

Authorization: Bearer jwt12345

Alternately, different kinds of commands may be used and the authorization token may be passed in whichever header is specified in the configuration. For example, a Python script can be used in the command:

kind: dynamic
location: header
name: Api-Key
command: python getApiKey.py
timeout: 300

If the output of python getApiKey.py is "apiKey6543", then Sift will send the following HTTP header in each request:

Api-Key: apiKey6543

Dynamic-HTTP-Header

A dynamic-http-header kind of authorization configures Sift to use a set of HTTP headers that are provided at runtime by execution of a command, and refreshed periodically according to a configured interval. Each dynamic-http-header authorization has the following required fields:

  • command: Command to execute to generate HTTP headers.
  • timeout: Interval in seconds at which the command will be executed.

Execution of command must produce on its standard output (stdout) a set of HTTP headers, one per line, in the form "Key: Value". Any leading and trailing whitespace will be trimmed.

Since the command may need to interact with the target application, the URL of the target is set in environment variable "SIFT_TARGET_URL" when the command is executed.

As an illustrative example, consider the following authorization configuration:

kind: dynamic-http-header
command: auth.sh
timeout: 120

and the Bash script auth.sh:

#!/bin/bash
echo "Authorization: Bearer jwt12345"
echo "X-TenantId: abcdef54321"

Sift will execute the auth.sh command at least once every 120 seconds, and use the headers read from the output. In each request, the authorization headers will be added to any other headers configured by the user (see "Additional Headers") or added by Sift's generated test sequences. Authorization headers override other user configured headers.

For the example above, the following HTTP headers will be included in a request (along with any other headers, not shown).

Authorization: Bearer jwt12345
X-TenantId: abcdef54321

Any language may be used to implement the command. The following example illustrates how to use Javascript to obtain a JWT token from a login API, and output an HTTP Authorization header with the bearer token.

#!/usr/bin/env node

//
// Example login script for Sift dynamic-http-header authorization plugin.
//
// This script performs a POST request to a login endpoint and obtains a JWT
// token from the response.  It outputs the necessary "Authorization" header
// with the bearer token value to stdout.  All of the headers output by the
// script to stdout will be used by Sift to authorize requests for the virtual
// user associated with this script.
//

// WARNING: Do NOT store secrets in a script.  For illustration only!
const userEmail ='[email protected]';
const userPass = 'MySecret';

// Using environment variable SIFT_TARGET_URL ensures this script will work
// with any target URL in the Sift configuration (or on Sift command-line).
const base_url = process.env.SIFT_TARGET_URL;
const login_url = `${base_url}/api/v1/user/login`;

const payload = { 'email': userEmail, 'password': userPass };

fetch(login_url, {
    method: "POST",
    headers: { "Content-type": "application/json" },
    body: JSON.stringify(payload),
})
.then((response) => {
    if (response.status !== 200) {
        console.log(`Login failed: status=${response.status}`);
        process.exit(1);
    }
    response.json().
        then(resp => {
            console.log(`Authorization: Bearer ${resp.data.jwtToken}`);
        })
})
.catch(error => {
  console.error('Error during login:', error.message);
  process.exit(1);
});

Additional Headers

The targets[].header property of a Target configures additional HTTP headers to send in each request. The property is a map of key-value pairs. For example, the following configuration adds a "Referer" header to each request to a Target.

header:
  Referer: https://example.com

The headers are added to every request, and have higher precedence than headers from authorization user identity (if the header fields are identical).

Proof-of-Possession (PoP) Token

The targets[].popToken property of a Target is an optional property to configure Sift to add a Proof-of-Possession (PoP) token to each request. A PoP token signs details of a request with a private key. The popToken property contains the following subfields:

  • privateKey: A required filename that contains a RSA private key in PEM format.
  • header: A required parameter that contains the HTTP header key into which a PoP token is added to a request.
  • fields: An optional array of fields of an HTTP request to sign in a PoP token. The values may be any header key or one of the pre-defined keywords 'http-method, 'uri', 'body'. The field values are extracted and added into the PoP token's 'edts' claim in the order that they appear.

If fields is empty or not specified, then 'edts and 'ehts' will be set to all header keys of a request, followed by 'http-method', 'uri', 'body' (in that order).

A field may not be present in a particular request (e.g., missing body, missing header key). In that case, the field name remains in the 'ehts' claim and the value of the field is treated as an empty string (i.e., no bytes added to 'edts' for that field).

Example:

  popToken:
    privateKey: ./path/to/popPrivateKey.pem
    header: X-Authorization
    fields:
    - http-method
    - uri
    - body

Operations Filter

The targets[].operations property configures a filter that selects which operations from a target API are invoked during an analysis run. An operation will be invoked when all include filters match, and no exclude filter matches. Any filter that is empty or not specified defaults to match. Filters that may be specified:

  • includeID: an array of Operation IDs. Match if operation's ID is present in the array.
  • excludeID: an array of Operation IDs. Match if operation's ID is present in the array.
  • includePath: an array of regular expressions that match path of an OpenAPI operation. Match if operation is an OpenAPI operation and the path of the operation matches a regular expression in the array. Ignored for any non-OpenAPI operation.
  • excludePath: an array of regular expressions that match path of an OpenAPI operation. Match if operation is an OpenAPI operation and the path of the operation matches a regular expression in the array. Ignored for any non-OpenAPI operation.

Rate Limit

targets[].rateLimit configures the rate at which Sift sends requests to a target API. The value of rateLimit is a floating point number of requests per second.

Examples:

  • 3: send no more than 3 requests per second.
  • 0.5: send no more than 1 request every 2 seconds.

Timeout

targets[].timeout configures the maximum duration for each request to a target. The value of timeout may be a number (in seconds) or a string that uses the following suffixes for time units: "h" for hours, "m" for minutes, "s" for seconds, "ms" for milliseconds. For example, a value of "1m30s" is equivalent to "90s" - both set the timeout to 90 seconds.

If timeout is not specified or value is zero, then the default timeout is 3 seconds. If the value is negative, then requests will not have a timeout (NOT RECOMMENDED).

Trace Header

If targets[].traceHeader is a non-empty string, then Sift sends a unique request identifier in this header field in every request. The identifier is unique among all requests sent to a particular target in a single analysis run. The request identifier can be used to trace or correlate a request with application logs.

The value of traceHeader should not conflict with the name of any header parameter defined in the API definition because it will override values that Sift is trying to use to analyze the application.

Run Parameters

The following optional properties may be specified at the top-level of the configuration to control how a run is executed.

Environment

environmentID specifies the ID of an Environment (defined in Platform) in which the analysis is being performed. This may also be overridden with CLI flag --env.

Fuzz Limit

fuzzLimit configures that number of attempts that are made to invoke each operation when constructing sequences of operations.

Labels

labels are user-defined metadata assigned to an analysis run. labels is a map of user-defined key-value pairs of strings.

Additional labels may be added with CLI flag --label.

Platform URL

platformURL specifies the location of the Aptori Platform to which results of the analysis run will be published.

This value is overridden by presence of any of the following, from highest to lowest priority:

  • CLI flag --platform;
  • environment variable SIFT_PLATFORM_URL.

Sequence Limit

sequenceLimit configures the maximum length for an operation sequence that is constructed during an analysis run. If sequenceLimit is not specified, then the default behavior is to construct sequences of up to 100 operations in length.

Time Limit

timeLimit configures the maximum duration of an analysis run. The duration is a string that may use the following suffixes for time units: "h" for hours, "m" for minutes, "s" for seconds. For example, to set a 12.5 minute time limit, use the string "12m30s".

NOTE: sift performs initialization and final transmission to the Aptori Platform outside of the analysis time limit. If there is an external limit on runtime, then it is recommended to configure timeLimit to be 30 seconds less than the external limit.