Scan images with twistcli
Prisma Cloud ships a command-line scanner for scanning container images and serverless functions. It is supported on Linux, macOS, and Windows.
Command reference
The
twistcli
command has several subcommands.
Use the twistcli images scan
subcommand to invoke the scanner.Projects
When users from a tenant project run twistcli, they must set the
--project
option to specify the proper context for the command.twistcli images scan --project "<project_name>"
Command
twistcli images scan
— Scan an image for vulnerabilities and compliance issues.
The image must reside on the system where twistcli runs.
If not, retrieve the image with docker pull
before scanning it.
Twistcli does not pull images for you.Synopsis
twistcli images scan [OPTIONS] [IMAGE]
Description
The
twistcli images scan
function collects information about the packages and binaries in the container image, and then sends it to Console for analysis.Data collected by twistcli includes:
- Packages in the image.
- Files installed by each package.
- Hashes for files in the image.
After Console analyzes the image for vulnerabilities,
twistcli
:- Outputs a summary report.
- Exits with a pass or fail return value.
Scan results can be retrieved in JSON format from the Console using API calls.
To specify an image to scan, use either the image ID, or repository name and tag.
The image should be present on the system, having either been built or pulled there.
If a repository is specified without a tag,
twistcli
looks for an image tagged latest
.When invoking
twistcli
, the last parameter should be the image to scan.
If you list options after the image, they will be ignored.Options
- ----addressURLRequired. URL for Console, including the protocol and port. Only the HTTPS protocol is supported. To get the address for your Console, go toCompute > Manage > System > Downloads, and copy the string underPath to Console.Example: --address https://us-west1.cloud.twistlock.com/us-3-123456789
- ---u,--userAccess Key IDAccess Key ID to access Prisma Cloud. If not provided, theTWISTLOCK_USERenvironment variable is used, if defined. Othewise, "admin" is used as the default.
- ---p,--passwordSecret KeySecret Key for the above Access Key ID specified with-u,--user. If not specified on the command-line, theTWISTLOCK_PASSWORDenvironment variable is used, if defined. Otherwise, you will be prompted for the user’s password before the scan runs.
Access Key ID and Secret Key are generated from the Prisma Cloud user interface.
For more information, see access keys
- ----output-fileFILENAMEWrite the results of the scan to a file in JSON format.Example:--output-file scan-results.json
- ----detailsShow all vulnerability details.
- ----containerizedRun the scan from inside the container.
- ----custom-labelsInclude the image custom labels in the results.
- ----docker-addressDOCKER_CLIENT_ADDRESSDocker daemon listening address (default:unix:///var/run/docker.sock). Can be specified with theDOCKER_CLIENT_ADDRESSenvironment variable.
- ----docker-tlscacertPATHPath to Docker client CA certificate.
- ----docker-tlscertPATHPath to Docker client Client certificate.
- ----docker-tlskeyPATHPath to Docker client Client private key.
- ----tlscacertPATHPath to Prisma Cloud CA certificate file. If no CA certificate is specified, the connection to Console is insecure.
- ----podman-pathPATHForces twistcli to use Podman. To use the default installation path, set aspodman. Otherwise, provide the appropriate path.
- ----include-js-dependenciesEvaluates packages listed only in manifests.
- ----tokenTOKENToken to use for Prisma Cloud Console authentication. Tokens can be retrieved from the API endpointapi/v1/authenticateor from theManage > Authenticate > User Certificatespage in Console.
RETURN VALUE
The exit code is 0 if
twistcli images scan
finds no vulnerabilities or compliance issues.
Otherwise, the exit code is 1.The criteria for passing or failing a scan is determined by the CI vulnerability and compliance policies set in Console.
The default CI vulnerability policy alerts on all CVEs detected.
The default CI compliance policy alerts on all critical and high compliance issues.
There are two reasons why
twistcli images scan
might return an exit code of 1.- The scan failed because the scanner found issues that violate your CI policy.
- Twistcli failed to run due to an error.
Although the return value is ambiguous — you cannot determine the exact reason for the failure by just examining the return value — this setup supports automation.
From an automation process perspective, you expect that the entire flow will work.
If you scan an image, with or without a threshold, either it works or it does not work.
If it fails, for whatever reason, you want to fail everything because there is a problem.
Scan results
To view scan reports in Console, go to
Monitor > Vulnerabilities > Images > CI
or Monitor > Compliance > Images > CI
.You can also retrieve scan reports in JSON format using the Prisma Cloud API, see the API section.
Output
The twistcli tool can output scan results to several places:
- stdout.
- File. Scan results are saved in JSON format.
- Console. Scan results can be viewed underMonitor > Vulnerabilities > Images > CI.
By passing certain flags, you can adjust how the twistcli scan output looks and where it goes.
By default, twistcli writes scan results to stdout and sends the results to Console.
To write scan results to stdout in tabular format, pass the
--details
flag to twistcli.
This does not affect where the results are sent.To write scan results to a file in JSON format, pass the
--output-file
flag to twistcli.
If you specify an output file, then results cannot be sent to Console.API
You can retrieve scan reports in JSON format using the Prisma Cloud Compute API.
The API returns comprehensive information for each scan report, including the full list of packages, files, and vulnerabilities.
The following example
curl
command calls the API with Basic authentication.
You’ll need to apply some filtering with tools like jq
to extract specific items from the response.
For more information on accessing the API, see Accessing the API.$ curl \ -u <COMPUTE_CONSOLE_USER> \ -o scan_results.json \ 'https://<COMPUTE_CONSOLE>/api/v1/scans?type=ciImage'
If you are using assigned collections, then specify the collection in a query parameter:
$ curl \ -u <COMPUTE_CONSOLE_USER> \ -o scan_results.json \ 'https://<COMPUTE_CONSOLE>/api/v1/scans?type=ciImage&collections=<COLLECTION_NAME>'
Dockerless scan
By default, twistcli is run from outside the container image.
Podman Twistcli scans
Twistcli can run scans on Podman hosts.
Use
--podman-path PATH
to specify the path to podman and force the twistcli scanner to use podman.
For additional information, see the Podman section.Running from inside of the container
In some cases, you might need to copy twistcli to the container’s file system, and then run the scanner from inside the container.
One reason you might want to run the scanner this way is when your build platform doesn’t give you access to the Docker socket.
CodeFresh is an example of such a platform.
There are some shortcomings with scanning from inside a container, so you should only use this approach when no other approach is viable.
The shortcomings are:
- Automating the scan in your continuous integration pipeline is more difficult.
- Image metadata, such as registry, repository, and tag aren’t available in the scan report. When twistcli is run from outside the container, this information is retrieved from the Docker API.
- The image ID isn’t available in the scan report because it cannot be determined when the scan is run from inside a container.
- The scan report won’t show a layer-by-layer analysis of the image.
Usage
When running the scanner from inside a container, you need to properly orient it by passing it the
--containerized
flag.
There are a couple of ways to run twistcli with the --containerized
flag: build-time and run-time.For security reasons, Prisma Cloud recommends that you create a user with the
CI User
role for running scans.Build-time invocation
After building an image, run it.
Mount the host directory that holds the twistcli binary, pass the Prisma Cloud Console user credentials to the container with environment variables, then run the scanner inside the container.
The
<REPORT_ID>
is a user defined string that uniquely identifies the scan report in the Console UI.$ docker run \ -v /PATH/TO/TWISTCLIDIR:/tools \ -e TW_USER=<COMPUTE_CONSOLE_USER> \ -e TW_PASS=<COMPUTE_CONSOLE_PASSWD> \ -e TW_CONSOLE=<COMPUTE_CONSOLE> \ --entrypoint="" \ <IMAGE_NAME> \ /tools/twistcli images scan \ --containerized \ --details \ --address $TW_CONSOLE \ --user $TW_USER \ --password $TW_PASS \ <REPORT_ID>
Rather than username and password, twistcli can also authenticate to Console with a token.
Your API token can be found in Console under
Manage > Authentication > User Certificates > API token
.$ docker run \ -v /PATH/TO/TWISTCLI_DIR:/tools \ -e TW_TOKEN=<API_TOKEN> \ -e TW_CONSOLE=<COMPUTE_CONSOLE> \ --entrypoint="" \ <IMAGE_NAME> \ /tools/twistcli images scan \ --containerized \ --details \ --address $TW_CONSOLE \ --token $TW_TOKEN \ <REPORT_ID>
Run-time invocation
If you have access to the orchestrator, you can exec into the running container to run the twistcli scanner.
Alternatively, you could SSH to the container.
Once you have a shell on the running container, invoke the scanner:
$ ./twistcli images scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ --containerized \ <REPORT_ID>
To invoke the scanner with an API token:
$ ./twistcli images scan \ --address <COMPUTE_CONSOLE> \ --token <API_TOKEN> \ --containerized \ <REPORT_ID>
Simple scan
Scan an image with twistcli and print the summary report to stdout.
- Scan an image namedmyimage:latest.$ twistcli images scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ myimage:latestCommand output:
Scan with detailed report
You can have twistcli generate a detailed report for each scan.
The following procedure shows you how to scan an image with twistcli, and then retrieve the results from Console.
- Scan an image namedmyimage:latest.$ twistcli images scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ --details \ myimage:latestSample command output (results have been truncated):
- This outputs a tabular representation of your scan results to stdout. If you need to retrieve the results of your scan in JSON format, this can be done using the API. For more information on the API, refer to Accessing the API.
- Call the API with authentication (demonstrated here using Basic authentication) to fetch the results of the scan.$ curl \ -o scan_results.json \ -H 'Authorization: Basic YXBpOmFwaQ==' \ 'https://<COMPUTE_CONSOLE>/api/v1/scans?search=myimage&limit=1&reverse=true&type=ciImage'
- Format the scan results into human-readable format.$ python -m json.tool scan_results.json > scan_results_pp.json
- Inspect the results.Openscan_results_pp.jsonto view the results. Vulnerability information can be found in thevulnerabilitiesarray, and compliance results can be found in thecomplianceIssuesarray.[ { "entityInfo": { "_id": "", "type": "ciImage", ... "complianceIssues": [ { "text": "", "id": 41, "severity": "high", "cvss": 0, "status": "", "cve": "", "cause": "", "description": "It is a good practice to run the container as a non-root user, if possible. Though user\nnamespace mapping is now available, if a user is already defined in the container image, the\ncontainer is run as that user by default and specific user namespace remapping is not\nrequired", "title": "(CIS_Docker_CE_v1.1.0 - 4.1) Image should be created with a non-root user", "vecStr": "", "exploit": "", "riskFactors": null, "link": "", "type": "image", "packageName": "", "packageVersion": "", "layerTime": 0, "templates": [], "twistlock": false, "published": 0, "discovered": "0001-01-01T00:00:00Z" } ], ... "vulnerabilities": [ { "text": "", "id": 46, "severity": "medium", "cvss": 9.8, "status": "deferred", "cve": "CVE-2018-20839", "cause": "", "description": "systemd 242 changes the VT1 mode upon a logout, which allows attackers to read cleartext passwords in certain circumstances, such as watching a shutdown, or using Ctrl-Alt-F1 and Ctrl-Alt-F2. This occurs because the KDGKBMODE (aka current keyboard mode) check is mishandled.", "title": "", "vecStr": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "exploit": "", "riskFactors": { "Attack complexity: low": {}, "Attack vector: network": {}, "Medium severity": {} }, "link": "https://people.canonical.com/~ubuntu-security/cve/2018/CVE-2018-20839", "type": "image", "packageName": "systemd", "packageVersion": "237-3ubuntu10.39", "layerTime": 1587690420, "templates": [], "twistlock": false, "published": 1558067340, "discovered": "0001-01-01T00:00:00Z", "binaryPkgs": [ "libnss-systemd", "libsystemd0", "libpam-systemd", "udev", "systemd-sysv", "libudev1", "systemd" ] }, ... ], ... }, ... } ]
Scan images built with Jenkins in an OpenShift environment
If you are building and deploying images on OpenShift Container Platform (OCP), and you are utilizing their Jenkins infrastructure, then invoke a scan with the
twistcli hosts scan
command, not the twistcli images scan
command.You can scan images generated by Jenkins with the OpenShift plugin by invoking twistcli from a
build hook.
Build hooks let you inject custom logic into the build process.
They run your commands inside a temporary container instantiated from build output image.
Build hooks are called when the last layer of the image has been committed, but before the image is pushed to a registry.
An non-zero exit code fails the build.
A zero exit code passes the build, and allows it to proceed to the next step.
To call twistcli from a build hook:
- Download twistcli into your build environment. Depending on your build strategy, one option is to download it as an external artifact using asave-artifactsS2I script.
- In yourBuildConfig, call twistcli as ascriptfrom thepostCommithook.$ twistcli hosts scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ --skip-docker \ --include-3rd-partyWhere the--skip-dockeroption skips all Docker compliance checks such as the Docker daemon configuration and the--include-3rd-partyoption scans application-specific files such as JARs.
Scan images when the Docker socket isn’t in the default location
The twistcli scanner uses the Docker API, so it must be able to access the socket where the Docker daemon listens.
If your Docker socket isn’t in the default location, use the
--docker-address
option to tell twistcli where to find it:- ----docker-addressPATHPath to the Docker socket. By default, twistcli looks for the Docker socketunix:///var/run/docker.sock.
$ ./twistcli images scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ --docker-address unix:///<PATH/TO>/docker.sock \ <IMAGE_NAME>
Scan Podman/CRI images
Podman is a daemon-less container engine for developing, managing, and running OCI containers on Linux.
The twistcli tool can use the preinstalled Podman binary to scan CRI images.
- ----podman-pathPATHForces twistcli to use Podman. To call podman from its default install path, specifypodman. Otherwise, specify an explicit path.$ ./twistcli images scan \ --address <COMPUTE_CONSOLE> \ --user <COMPUTE_CONSOLE_USER> \ --password <COMPUTE_CONSOLE_PASSWD> \ --podman-path podman \ <IMAGE_NAME>
CI/CD Automation
Twistcli images scan can be used to shift-left security scans inside of your build pipeline.
Plugins are available for Jenkins and other CI/CD tools, but twistcli can also be used from a CI pipeline in order to initiate vulnerability and compliance scans on images.
The exit status code can be verified inside of your pipeline to determine pass and fail status of the image scan.
A zero exit code signals the scan passes, and any non-zero exit code signals a failure.
In order to automate the download and version sync of twistcli, reference the sample Jenkins code below:
stage('Check twistcli version') { def TCLI_VERSION = sh(script: "./twistcli | grep -A1 VERSION | sed 1d", returnStdout:true).trim() def CONSOLE_VERSION = sh(script: "curl -k -u \"$TL_USER:$TL_PASS\" https://$TL_CONSOLE/api/v1/version | tr -d \'\"'", returnStdout:true).trim() println "TCLI_VERSION = $TCLI_VERSION" println "CONSOLE_VERSION = $CONSOLE_VERSION" if ("$TCLI_VERSION" != "$CONSOLE_VERSION") { println "downloading twistcli" sh 'curl -k -u $TL_USER:$TL_PASS --output ./twistcli https://$TL_CONSOLE/api/v1/util/twistcli' sh 'sudo chmod a+x ./twistcli' } } stage('Scan with Twistcli') { sh './twistcli images scan --address https://$TL_CONSOLE -u $TL_USER -p $TL_PASS --details $IMAGE' }
Using twistcli with Prisma Cloud Compute in Enterprise Edition
The following procedure is true even if IP whitelisting feature is enabled in Prisma Cloud.
You can use your username:password from PC or Access Key / Secret Key created by a user as username:password in twistcli calls.
- Go to Settings > Access Keys page under Prisma Cloud
- Create an Access Key with desired expiration time. Make sure you keep this secure by downloading or copying for future use.
- Get Compute Console URL from Compute tab - Manage > System > Downloads.
- Use Access Key as username and Secret key as password for your twistcli calls./twistcli images scan --address <Console> --username <ACCESS_KEY> --password <SECRET_KEY> ubuntu:latest
Recommended For You
Recommended Videos
Recommended videos not found.