CodeQL: Analysis of Swift Code on Linux (x86_64)

Swift is primarily used to build applications targeted for running on Apple platforms. However, the Swift Static SDK enables developers to build programs as statically linked executables for other target platforms, such as Linux/Windows.

This post is a basic introduction to using CodeQL for scanning Swift code on an Ubuntu-22.04 host.

Install Swift

The following bash script can be used to install Swift on Ubuntu-20.04.

#!/bin/bash

apt-get install \
          binutils \
          git \
          gnupg2 \
          libc6-dev \
          libcurl4-openssl-dev \
          libedit2 \
          libgcc-11-dev \
          libpython3-dev \
          libsqlite3-0 \
          libstdc++-11-dev \
          libxml2-dev \
          libz3-dev \
          pkg-config \
          python3-lldb-13 \
          tzdata \
          unzip \
          zlib1g-dev

os_version=$(lsb_release -rs)

latest_swift_release_tag=$(gh api \
    -H "Accept: application/vnd.github+json" \
    -H "X-GitHub-Api-Version: 2022-11-28" /repos/swiftlang/swift/releases --paginate |
    jq -r 'map(select(.draft==false and .prerelease==false))|max_by(.published_at)|.tag_name')

download_url="https://download.swift.org/${latest_swift_release_tag,,}/ubuntu${os_version//./}/${latest_swift_release_tag}/${latest_swift_release_tag}-ubuntu${os_version}.tar.gz"
download_path="/tmp/$(basename "$download_url")"
curl -sSLo "$download_path" "$download_url"

wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -

tar xzf "$download_path" -C /tmp

SWIFT_INSTALL_ROOT="/usr/share/swift"
swift_bin_root="$SWIFT_INSTALL_ROOT/usr/bin"
swift_lib_root="$SWIFT_INSTALL_ROOT/usr/lib"

mv "/tmp/${latest_swift_release_tag}-ubuntu${os_version}" $SWIFT_INSTALL_ROOT
mkdir -p /usr/local/lib

ln -s "$swift_bin_root/swift" /usr/local/bin/swift
ln -s "$swift_bin_root/swiftc" /usr/local/bin/swiftc
ln -s "$swift_lib_root/libsourcekitdInProc.so" /usr/local/lib/libsourcekitdInProc.so

Ensure the script is executable:

$ chmod +x install-swift.sh

Run the install:

$ sudo ./install-swift.sh

Install Swift Static SDK

Install Swift Static SDK for Linux.

$ swift sdk install https://download.swift.org/swift-6.0.1-release/static-sdk/swift-6.0.1-RELEASE/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz \
--checksum d4f46ba40e11e697387468e18987ee622908bc350310d8af54eb5e17c2ff5481

Confirm the SDK has been installed successfully by reviewing the output from the following:

$ swift sdk list

Sample Swift Project

Create a work area to store source code:

$ mkdir $HOME/sample-swift
$ cd $HOME/sample-swift

Create Swift package:

$ swift package init --type executable

CodeQL Code Scanning

Run CodeQL for our sample project.

Create Database

Create CodeQL database:

$ cd $HOME/sample-swift
$ codeql database create --language=swift --command="swift build" ./swift-db

Sample output:

Initializing database at ***sample-swift/swift-db.
Running build command: [swift, build]
Running command in ***/sample-swift: [swift, build]
...
Successfully created database at ***/sample-swift/swift-db.

Run Analysis

Run the analysis:

$ codeql database analyze ./swift-db --format=sarifv2.1.0 --output=./results.sarif

Sample output log:

Running queries.
[1/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-1204/StaticInitializationVector.qlx.
[2/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-311/CleartextStorageDatabase.qlx.
[3/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-311/CleartextTransmission.qlx.
[4/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-089/SqlInjection.qlx.
[5/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-757/InsecureTLS.qlx.
[6/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-078/CommandInjection.qlx.
[7/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-020/IncompleteHostnameRegex.qlx.
[8/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-020/MissingRegexAnchor.qlx.
[9/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-079/UnsafeWebViewFetch.qlx.
[10/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-312/CleartextLogging.qlx.
[11/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-312/CleartextStoragePreferences.qlx.
[12/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-259/ConstantPassword.qlx.
[13/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-116/BadTagFilter.qlx.
[14/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-611/XXE.qlx.
[15/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-760/ConstantSalt.qlx.
[16/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-328/WeakSensitiveDataHashing.qlx.
[17/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-328/WeakPasswordHashing.qlx.
[18/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-916/InsufficientHashIterations.qlx.
[19/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-321/HardcodedEncryptionKey.qlx.
[20/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-943/PredicateInjection.qlx.
[21/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-134/UncontrolledFormatString.qlx.
[22/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-135/StringLengthConflation.qlx.
[23/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-730/RegexInjection.qlx.
[24/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-022/PathInjection.qlx.
[25/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-1333/ReDoS.qlx.
[26/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/queries/Security/CWE-327/ECBEncryption.qlx.
[27/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/diagnostics/internal/ExtractionErrors.qlx.
[28/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/diagnostics/ExtractedFiles.qlx.
[29/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/diagnostics/SuccessfullyExtractedLines.qlx.
[30/30] Loaded ***/apps/codeql-cli/qlpacks/codeql/swift-queries/0.3.16/diagnostics/internal/UnresolvedAstNodes.qlx.
ExtractedFiles.ql             : [1/30 eval 1.2s] Results written to codeql/swift-queries/diagnostics/ExtractedFiles.bqrs.
SuccessfullyExtractedLines.ql : [2/30 eval 26ms] Results written to codeql/swift-queries/diagnostics/SuccessfullyExtractedLines.bqrs.
ExtractionErrors.ql           : [3/30 eval 4ms] Results written to codeql/swift-queries/diagnostics/internal/ExtractionErrors.bqrs.
UnresolvedAstNodes.ql         : [4/30 eval 56ms] Results written to codeql/swift-queries/diagnostics/internal/UnresolvedAstNodes.bqrs.
IncompleteHostnameRegex.ql    : [5/30 eval 1.7s] Results written to codeql/swift-queries/queries/Security/CWE-020/IncompleteHostnameRegex.bqrs.
MissingRegexAnchor.ql         : [6/30 eval 16ms] Results written to codeql/swift-queries/queries/Security/CWE-020/MissingRegexAnchor.bqrs.
PathInjection.ql              : [7/30 eval 146ms] Results written to codeql/swift-queries/queries/Security/CWE-022/PathInjection.bqrs.
CommandInjection.ql           : [8/30 eval 46ms] Results written to codeql/swift-queries/queries/Security/CWE-078/CommandInjection.bqrs.
UnsafeWebViewFetch.ql         : [9/30 eval 19ms] Results written to codeql/swift-queries/queries/Security/CWE-079/UnsafeWebViewFetch.bqrs.
SqlInjection.ql               : [10/30 eval 23ms] Results written to codeql/swift-queries/queries/Security/CWE-089/SqlInjection.bqrs.
BadTagFilter.ql               : [11/30 eval 16ms] Results written to codeql/swift-queries/queries/Security/CWE-116/BadTagFilter.bqrs.
StaticInitializationVector.ql : [12/30 eval 18ms] Results written to codeql/swift-queries/queries/Security/CWE-1204/StaticInitializationVector.bqrs.
ReDoS.ql                      : [13/30 eval 19ms] Results written to codeql/swift-queries/queries/Security/CWE-1333/ReDoS.bqrs.
UncontrolledFormatString.ql   : [14/30 eval 55ms] Results written to codeql/swift-queries/queries/Security/CWE-134/UncontrolledFormatString.bqrs.
StringLengthConflation.ql     : [15/30 eval 82ms] Results written to codeql/swift-queries/queries/Security/CWE-135/StringLengthConflation.bqrs.
ConstantPassword.ql           : [16/30 eval 15ms] Results written to codeql/swift-queries/queries/Security/CWE-259/ConstantPassword.bqrs.
CleartextStorageDatabase.ql   : [17/30 eval 256ms] Results written to codeql/swift-queries/queries/Security/CWE-311/CleartextStorageDatabase.bqrs.
CleartextTransmission.ql      : [18/30 eval 74ms] Results written to codeql/swift-queries/queries/Security/CWE-311/CleartextTransmission.bqrs.
CleartextLogging.ql           : [19/30 eval 83ms] Results written to codeql/swift-queries/queries/Security/CWE-312/CleartextLogging.bqrs.
CleartextStoragePreferences.ql: [20/30 eval 14ms] Results written to codeql/swift-queries/queries/Security/CWE-312/CleartextStoragePreferences.bqrs.
HardcodedEncryptionKey.ql     : [21/30 eval 61ms] Results written to codeql/swift-queries/queries/Security/CWE-321/HardcodedEncryptionKey.bqrs.
ECBEncryption.ql              : [22/30 eval 35ms] Results written to codeql/swift-queries/queries/Security/CWE-327/ECBEncryption.bqrs.
WeakPasswordHashing.ql        : [23/30 eval 50ms] Results written to codeql/swift-queries/queries/Security/CWE-328/WeakPasswordHashing.bqrs.
WeakSensitiveDataHashing.ql   : [24/30 eval 44ms] Results written to codeql/swift-queries/queries/Security/CWE-328/WeakSensitiveDataHashing.bqrs.
XXE.ql                        : [25/30 eval 25ms] Results written to codeql/swift-queries/queries/Security/CWE-611/XXE.bqrs.
RegexInjection.ql             : [26/30 eval 60ms] Results written to codeql/swift-queries/queries/Security/CWE-730/RegexInjection.bqrs.
InsecureTLS.ql                : [27/30 eval 43ms] Results written to codeql/swift-queries/queries/Security/CWE-757/InsecureTLS.bqrs.
ConstantSalt.ql               : [28/30 eval 16ms] Results written to codeql/swift-queries/queries/Security/CWE-760/ConstantSalt.bqrs.
InsufficientHashIterations.ql : [29/30 eval 14ms] Results written to codeql/swift-queries/queries/Security/CWE-916/InsufficientHashIterations.bqrs.
PredicateInjection.ql         : [30/30 eval 205ms] Results written to codeql/swift-queries/queries/Security/CWE-943/PredicateInjection.bqrs.
Shutting down query evaluator.
Interpreting results.
CodeQL scanned 1 out of 2 Swift files in this invocation. Typically CodeQL is configured to analyze a single CodeQL language per invocation, so check other invocations to determine overall coverage information.
Analysis produced the following metric data:

|             Metric             | Value |
+--------------------------------+-------+
| Number of unresolved AST nodes |     0 |