Skip to main content
Version: File Inspection Engine 1.4.0

Usage

The File Inspection Engine starts in approximately 4 seconds, assuming that the static analysis engine initializes successfully and the license is valid. You can confirm that the application is ready by checking if the readiness endpoint returns 200 OK.

note

When starting for the first time, the application needs to download threat data. This process may take some time, and the application will only become fully usable once the threat data download is complete, regardless of the messages displayed.

If the static analysis engine fails to initialize, the application will exit. For all other errors, logs will be generated, and the application will continue to run.

File Submissions

POST /scan

To scan a file, make a POST request to http://<host>:<port>/scan, with the file contents as the raw request body.

  • You don’t need to set the Content-Type header. If set, it will be included alongside every log message related to that submission.
  • It is recommended to set the Content-Length header to prevent files larger than the maximum upload size from partially uploading before getting rejected.
  • Optionally, you can provide an external_id query string parameter that will also be included alongside log messages related to the submission. This parameter can contain any value meaningful to the client application, such as a file name, database ID, or other identifying information.

Examples using curl

Example request:

curl -X POST --upload-file example.docx http://<host>:<port>/scan

Example response:

{
"classification": "OK",
"message": "",
"errors": []
}

Classification: The classification string will be either "OK" or "malicious". If paranoid mode is turned on, the classification could also be "suspicious".

If with-threat-details and add-file-type options are enabled, the response may look like:

{
"classification": "malicious",
"message": "",
"errors": [],
"threat_details": {
"platform": "Script",
"type": "Trojan",
"threat_name": "Script-JS.Trojan.Redirector"
},
"file_type": "Text"
}

Logging:

The following example provides Content-Type and a custom external ID in the request, both of which can be visible in application logs:

curl -v -X POST -H 'Content-Type: application/x-tar' --upload-file archive.tar 'http://localhost:8000/scan?external_id=my%20external%20id'

Log example:

This request would create the following log entry, including the external ID:


{
"level": "info",
"request_id": "21e7262b-28a0-43a0-be4e-a6f0a5d897a3",
"external_id": "my external id",
"content_type": "application/x-tar",
"component": "http.api",
"request_path": "/scan",
"content_length": 244244480,
"active_concurrency": 1,
"time": "2024-11-27T13:41:52.593520919+01:00",
"message": "Upload started"
}

Error handling

If there are any errors, they will be returned in the message field (deprecated), as well as the errors field. The message field will contain the same errors as the errors array, only it will be a semicolon-concatenated string. For example:

{
"message": "error one; error two; error three",
"errors": ["error one", "error two", "error three"]
}

In some cases, certain errors are expected, and are converted to additional properties inside analysis_information. For example, if a file hits the decompression factor limit, this error will be logged in errors and message, but also present in analysis_information.partial_unpacking.

{
"errors": ["Exceeds decompression ratio."],
"message": "Exceeds decompression ratio.",
"analysis_information": {
"partial_unpacking": true
}
}

Response Status Codes

The errors and message fields may contain soft errors (e.g., failing to get detailed threat information from the cloud), but are often empty. Hard errors will be returned as HTTP status 500 Internal Server Error.

CodeDescriptionMessage
200The request has succeeded.N/A
400File size error.{"error": "Maximum upload file size in bytes is {configured_value}" }
429Concurrency limit reached.{"error": "The concurrent analysis limit has been reached"}
429High processing load{"error": "The application is not ready for processing"}
524A timeout occurred.{"error": "The analysis could not be completed within the configured maximum analysis time"}

File Rejection

When a /scan upload request reaches an FIE instance, the engine first performs a readiness check before accepting the file for processing.

Depending on the setup, readiness checks can be approached in two ways:

  • Kubernetes Readiness: Point your container’s readiness probe to /readyz. When a container fails its readiness check, Kubernetes marks the Pod as not ready, and Services automatically stop routing traffic to it.

  • External Load Balancer: Configure your load balancer’s health check on /readyz so only ready instances receive traffic. These probes are helpful to keep traffic away from busy nodes, but they are optional. The engine also performs its own readiness check for each file upload.

note

Depending on the delay between the readiness check and the file submission, it is possible that the application returns a ready state, but the file can still be rejected if the conditions change. Such files will have to be resubmitted.

The engine evaluates several conditions to determine whether a file can be accepted. Some conditions are influenced by system state, such as memory usage or processing load, while others, such as concurrency, are driven by the volume of incoming requests. Logging occurs when any of these conditions change, regardless of file submission activity.

Memory Usage

The system can optionally track memory usage and compare it to a configured threshold (processing-unavailable-at-memory-percent). When enabled, memory usage is calculated as a percentage of either:

If this threshold is exceeded at the time of file submission, the application will reject the file until memory usage drops below the limit.

note

If the temporary directory is configured as tmpfs, it will be counted toward memory usage.

Because memory usage depends on the complexity and unpacking behavior of previously submitted files, it may remain elevated even after no new uploads occur. The system logs when it enters and exits high-memory conditions independently of file submissions.

If the threshold is not configured, memory usage is not tracked or logged, and file rejection based on memory use is disabled.

Concurrency Limit

The system also enforces a limit on concurrent requests, defined by the concurrency-limit setting. If the number of active concurrent requests exceeds this limit, new submissions will be temporarily rejected.

Even if the concurrency limit is set to 0 (unlimited), the system still tracks the number of active concurrent requests.

Concurrency is controlled by the number of active file submissions at any given moment. This value is directly influenced by the client’s submission behavior, making it a more predictable limit compared to memory or processing-based conditions.

Logging

If a file upload is rejected due to memory or processing conditions, the application will return the HTTP status 429 Too Many Requests.

The application logs when it enters and exits high-load or high-memory states. These log entries are independent of file submission attempts, since resource usage is influenced by the complexity of previously submitted files, not just their size or frequency.

Log Examples

Processing Load: High and Normal

{
"level": "warn",
"component": "readiness.Controller",
"time": "2025-05-09T10:22:02.657110286Z",
"message": "High processing load"
}
{
"level": "info",
"component": "readiness.Controller",
"time": "2025-05-09T10:30:06.586485173Z",
"message": "High processing load finished"
}

Memory Usage: High and Normal

{
"level": "warn",
"component": "readiness.Controller",
"time": "2025-05-09T10:35:48.534127292Z",
"message": "Memory use is above the threshold of 90%"
}
{
"level": "info",
"component": "readiness.Controller",
"time": "2025-05-09T10:35:53.53230899Z",
"message": "Memory use is below the threshold of 90%"
}

Timeouts

If timeouts are configured for uploads, they apply to all processing after the upload is complete.

Analyses may fail due to one of two reasons:

  • Complex file: The file is too complex and it will never be analyzed within the configured time limit, even when the server is idle. Waiting and trying again will not help.

  • Server load: The file is a bit more complex relative to the current load on the server. If the server were less busy, it might be possible to process it within the configured time limit. Waiting and trying again might help.

Check Application Liveness

curl http://<host>:<port>/livez

Returns 200 OK if the application process is running. Use for Kubernetes liveness probes.

Check Application Readiness

curl http://<host>:<port>/readyz

Returns 200 OK only if:

  • The engine has fully initialized (including license validation) and is not too busy to process samples.

  • Current resource utilization is within configured limits (memory, concurrency) and the system is not too busy (Spectra Core, CPU/load) to process samples.

  • If not ready, returns a 4xx or 5xx status.

Check Application Version / License / Configuration

GET /status

To check the File Inspection Engine version, license expiration date, threat data timestamp, and configuration, use the /status endpoint.

The config section contains all the configurable options and their current values. Values containing sensitive information are redacted.

curl http://<host>:<port>/status
{
"config": {
"add_file_type": "disabled",
"cloud_update_interval": "5m0s",
"cloud_updates": true,
"concurrency_limit": 20,
"http_address": ":8000",
"log_json": true,
"max_decompression_factor": 1,
"max_upload_file_size": 100,
"paranoid_mode": false,
"processing_unavailable_at_memory_percent": 0
"proxy_address": "http://user:xxxxx@proxy.company.lan",
"timeout": "0s",
"unpacking_depth": 17,
"with_threat_details": false
},
"license": {
"valid_until": "2025-06-01"
},
"version": {
"application": "1.2.0",
"threat_data": "2025-02-26T17:44:50Z"
}
}