Skip to content

Unified: Add command injection query. - #22879

Open
geoffw0 wants to merge 10 commits into
github:mainfrom
geoffw0:unifiedcommandinjection
Open

geoffw0 wants to merge 10 commits into
github:mainfrom
geoffw0:unifiedcommandinjection

Conversation

@geoffw0

@geoffw0 geoffw0 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Adds a unified/swift/command-line-injection query for unified Swift. I got Copilot to do this step-by-step, first copying files from the original Swift implementation, then updating the structure, porting the QL itself, and finally fixing a couple of issues. The original tests are preserved and test annotations updated so we can see where we stand. Tiny bit of manual fixup afterwards.

I'll share a skill to do all this when it's sufficiently mature / proven.

The query only finds a couple of the test cases right now. I'm pretty sure we're missing some relevant summary models, and there might be other issues e.g. with data flow. But it's time to share what I have and open it up to discussion.

DCA run LGTM - no issues, no results found, hardly surprising with such limited success on tests. Lots of work needed on data flow and probably some follow-up work on summary models.

geoffw0 and others added 7 commits October 23, 2026 17:59
Copy the original Swift query, help, examples, and regression test files unchanged as a reviewable baseline for the unified port. Metadata, imports, and test references will be adapted in subsequent commits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Inline CommandInjectionQuery.qll and CommandInjectionExtensions.qll in the query, preserving their declarations and required shared imports. Keep this source-collection step separate from the unified API port; the query is not expected to compile yet.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use unified taint tracking and the existing command-injection models, update the query ID and test reference, and enable inline expectation checks. Leave TODOs for Process property sinks and the original numeric barrier.

Learn the focused regression test and annotate missing behavior explicitly. The query currently reports two alerts with no inline expectation failures; further modeling and flow improvements are left for follow-up commits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the model-as-data selector for calls that omit terminationHandler, retaining the existing full-argument model. This detects the previously missing executable-URL case without query-local model code.

Cover explicit and omitted termination handlers with positive and safe cases. The command-injection test now reports four alerts with no expectation failures; both it and the path-injection test pass without --learn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the OWASP link returning 404 with its current canonical page (verified HTTP 200). Explain fixed executables, separate arguments, and allowlisting complete shell commands so the guidance matches the examples.

Clarify which test comments describe original Swift false positives or currently missing alerts. Help XML and example paths validate, and the focused test passes with unchanged results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ll they don't really fix anything just rephrase?).
@geoffw0 geoffw0 added no-change-note-required This PR does not need a change note Unified labels Oct 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

QHelp previews:

unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp

System command built from user-controlled sources

Constructing a system command with unsanitized user input is dangerous, since a malicious user may be able to craft input that executes arbitrary code.

Recommendation

If possible, use hard-coded string literals to specify the command to run. Instead of interpreting user input directly as command names, examine the input and then choose among hard-coded string literals.

If this is not possible, then add sanitization code to verify that the user input is safe before using it.

Example

The following example executes code from user input without sanitizing it first:

var task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", userControlledString] // BAD

task.launch()

If user input is used to construct a command it should be checked first. This ensures that the user cannot insert characters that have special meanings:

func validateCommand(_ command: String) -> String? {
    let allowedCommands = ["ls -l", "pwd", "echo"]
    if allowedCommands.contains(command) {
        return command
    }
    return nil
}

if let validatedString = validateCommand(userControlledString) {
    var task = Process()
    task.launchPath = "/bin/bash"
    task.arguments = ["-c", validatedString] // GOOD

    task.launch()
}

References

Comment thread unified/ql/lib/ext/legacy-swift.model.yml
@geoffw0
geoffw0 marked this pull request as ready for review October 26, 2026 18:55
@geoffw0
geoffw0 requested a review from a team as a code owner October 26, 2026 18:55
Copilot AI max review requested due to automatic review settings October 26, 2026 18:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Source selection and sink matching can produce command-injection alerts for trusted data or unrelated APIs.

2 open issues
What changed in this PR

Adds an initial command-injection query to Unified’s Swift security analysis, with ported tests documenting current detection gaps.

Changes:

  • Add a taint-tracking path query using legacy Swift models.
  • Port query help, safe and unsafe examples, and annotated regression tests.
  • Model Process.run calls that omit the termination handler.
File Description
unified/​ql/​test/​query-tests/​security/​CWE-078/​CommandInjection/​CommandInjection.swift Ports Swift test cases and marks known detection gaps.
unified/​ql/​test/​query-tests/​security/​CWE-078/​CommandInjection/​CommandInjection.qlref Runs the query with inline-expectation checking.
unified/​ql/​test/​query-tests/​security/​CWE-078/​CommandInjection/​CommandInjection.expected Records current alerts and taint paths.
unified/​ql/​src/​queries/​security/​CWE-078/​CommandInjectionGood.swift Demonstrates command allowlisting.
unified/​ql/​src/​queries/​security/​CWE-078/​CommandInjectionBad.swift Demonstrates unsafe shell-command construction.
unified/​ql/​src/​queries/​security/​CWE-078/​CommandInjection.ql Defines the command-injection query and metadata.
unified/​ql/​src/​queries/​security/​CWE-078/​CommandInjection.qhelp Documents the risk, recommendations, and examples.
unified/​ql/​lib/​ext/​legacy-swift.model.yml Adds the shortened Process.run signature.

Review effort: Max

Comment thread unified/ql/lib/ext/legacy-swift.model.yml
Comment thread unified/ql/src/queries/security/CWE-078/CommandInjection.ql
@asgerf

asgerf commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

I've opened #22898 to fix the buggy 'Check query IDs' CI check

@geoffw0 geoffw0 added the ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. label Oct 27, 2026
@geoffw0

geoffw0 commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Docs team, this is a direct port of a query from our original Swift to unified Swift language (technically different at the CodeQL level, but the same target language as far as users are concerned). The .qhelp is copied from Swift and the only change was fixing a dead link (the same one as in #22880 updated).

Do you want to review future PRs like this when they're just copies from Swift to unified Swift? Do you want to review them if they have only very minor doc changes (fixing dead links, typos, changes to the example code)?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation no-change-note-required This PR does not need a change note ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. Unified

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants