Skip to content

Rust: Implement a new query for non-HTTPs URLs #20417

@geoffw0

Description

@geoffw0

Add a new CodelQL query for detecting the use of non-HTTPs URLs in Rust code. That is, a query that detects when Rust code may be accessing an http (rather than https) URL, which is likely to be a security issue.

This will work similarly to existing non-HTTPs URL queries we have for other target languages, for example:

  • java/non-https-url (java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql) for non-HTTPs URLs accessed in Java code.
  • cpp/non-https-url (cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql) for non-HTTPs URLs accessed in C/C++ code.

However the target language for this query will be Rust, the QL should be written to analyse Rust code and in a style consistent with our existing Rust queries - as a preference to the style of the Java and CPP queries above. For a style example see this existing SQL injection query for Rust:

  • rust/sql-injection (rust/ql/src/queries/security/CWE-089/SqlInjection.ql)

You will need to create the following files:

  • rust/ql/src/queries/security/CWE-319/UseOfHttpBad.rs - a simple example demonstrating the vulnerability, written in Rust code. This could be ported from the Java or CPP example in the equivalent location, or written from scratch, but either way it should be in concise, clear, idiomatic Rust. For readability we usually just want to show one case in the example, and save any interesting variations for the tests.
  • rust/ql/src/queries/security/CWE-319/UseOfHttpGood.rs - a fixed version of the Bad example that no longer exhibits the vulnerability.
  • rust/ql/src/queries/security/CWE-319/UseOfHttp.qhelp - a .qhelp file describing the query / vulnerability. Use a corresponding .qhelp from one of the other languages as a starting point, but translate any language specific parts to refer to Rust and update any language specific links you find (or remove them if you can't find an equivalent reference).
    • note that you do not need to include a link to the CWE definition at cwe.mitre.org, since the qhelp processor adds these automatically.
  • rust/ql/src/queries/security/CWE-319/UseOfHttp.ql - the query itself, including any required dataflow configuration (module ... implements DataFlow::ConfigSig) for tracking HTTP URLs from their definition to where they are used. Again, look to the three examples I have provided above to produce a quality Rust query for non-HTTPs URLs.
  • rust/ql/lib/codeql/rust/security/UseOfHttpExtensions.qll - defining sources, sinks and potentially barriers needed by the query. Once again, look to the three examples as a guide, and the Rust query in particular for how best to lay out the code.
    • we will need to define the sources in CodeQL, similarly to Java and CPP HttpStringLiteral classes. Note that StringLiteral is called StringLiteralExpr in CodeQL for Rust, and it has a method .getTextValue().
    • for sinks, I believe the existing models-as-data request-url sinks will be sufficient for now - use sinkNode(this, "request-url").
  • rust/ql/test/query-tests/security/CWE-319/main.rs - a Rust source file containing multiple examples of code containing non-HTTPs URL vulnerabilities (i.e. that the query should find), and multiple examples of code that is fixed or not vulnerable. Your Bad and Good examples should be included as part of this test, and you should use "inline expectations" comments to mark lines where you expect query results: // $ Alert[rust/non-https-url].
  • rust/ql/test/query-tests/security/CWE-319/options.yml - defines any dependencies required by the test.
  • rust/ql/test/query-tests/security/CWE-319/UseOfHttp.qlref - links to the UseOfHttp.ql file, so that the test runner can find the query. Also defines the test post-processing steps that should be performed.
  • rust/ql/test/query-tests/security/CWE-319/UseOfHttp.expected - this file contains the results from the test runner. Do not attempt to fill this in yourself - have the test runner generate it:
    1. download and extract CodeQL CLI: cd /tmp && curl -L -o codeql-linux64.zip https://github.com/github/codeql-cli-binaries/releases/latest/download/codeql-linux64.zip && unzip -q codeql-linux64.zip
    2. add to PATH: export PATH="/tmp/codeql:$PATH"
    3. from the test directory, codeql test run . --learn.
    • the most important section of the .expected file is the #select section containing the results of the query.
    • it's OK if the query doesn't find every result we wanted. If it finds nothing, we can work to debug it together.
  • rust/ql/test/query-tests/security/CWE-319/Cargo.lock - this file is also generated by the test runner, and should be committed.

In most cases equivalent files to the ones you need to create will exist for all three existing queries I have cited - though exact file names may differ a little. I strongly recommend you look at each of these, as it's likely they contain everything you need to succeed at this task. Note that the CodeQL libraries are slightly different depending on the target language, so when in doubt, lean towards how things are done in the Rust query.

If you run into any problems and get stuck, feel free to stop and ask for help!


When the work is done, I request that you complete a few final cleanup / admin tasks:

  • run the CodeQL CLI autoformatter on all .ql and .qll files you have written. With the CodeQL CLI installed: codeql query format [file] --in-place.
  • add any new query .ql file to the suite lists in rust/ql/integration-tests/query-suite. Typically new security queries should be in the rust-security-and-quality.qls.expected and rust-security-extended.qls.expected lists, and if they have the @precision high tag also rust-code-scanning.qls.expected.
  • add a brief change note file in rust/ql/src/change-notes. See https://github.com/github/codeql/blob/main/docs/change-notes.md for more information about change notes.
  • add any *Extensions.qll file containing classes that extend QuerySink::Range as an import in rust/ql/src/queries/summary/Stats.qll. This is to ensure that the new query sinks are visible to our statistics module.

Metadata

Metadata

Assignees

Labels

RustPull requests that update Rust code

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions