Rust: Model futures-io, rustls, futures-rustls#19626
Conversation
…g (reference). We shouldn't need these.
There was a problem hiding this comment.
Pull Request Overview
This PR adds CodeQL models and tests to improve taint-tracking for asynchronous I/O in Rust, covering futures-io, rustls, and futures-rustls. It also fixes test sink recognition in the web_frameworks suite.
- Introduce
test_futures_io.rsandtest_rustlsintest.rsto exerciseAsyncRead/AsyncBufReadpatterns over TLS streams. - Add dependency entries for
rustls,futures-rustls, andasync-stdinoptions.yml. - Provide new model YAMLs (
rustls.model.yml,futures.model.yml,async-rs.model.yml) to define taint sources and summaries for the relevant crates.
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs | Update expected sink annotations from $ MISSING to $ hasTaintFlow. |
| rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs | New tests covering AsyncRead/AsyncBufRead over TLS streams. |
| rust/ql/test/library-tests/dataflow/sources/test.rs | Add test_rustls function and invoke it from main. |
| rust/ql/test/library-tests/dataflow/sources/options.yml | Add rustls, futures-rustls, and async-std dependencies. |
| rust/ql/test/library-tests/dataflow/sources/TaintSources.expected | Update expected taint alerts for new connection and args sources. |
| rust/ql/test/library-tests/dataflow/sources/InlineFlow.ql | Broaden sink matching predicate to %::sink. |
| rust/ql/lib/codeql/rust/frameworks/rustls.model.yml | Add source/summary model entries for rustls and futures-rustls. |
| rust/ql/lib/codeql/rust/frameworks/futures.model.yml | Add summary model entries for futures-util I/O and streams. |
| rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml | Add source model entry for async-std TCP connect. |
| extensible: summaryModel | ||
| data: | ||
| - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "<crate::TlsConnector>::connect", "Argument[1]", "ReturnValue.Future.Field[crate::result::Result::Ok(0)]", "taint", "manual"] | ||
| - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "<crate::client::TlsStream as crate::if_std::AsyncRead>::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] |
There was a problem hiding this comment.
Add a summaryModel entry for <crate::client::TlsStream as crate::if_std::AsyncBufRead>::poll_fill_buf so that taint is correctly propagated through buffered reads, mirroring the existing poll_read rule.
| - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "<crate::client::TlsStream as crate::if_std::AsyncRead>::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "<crate::client::TlsStream as crate::if_std::AsyncRead>::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "<crate::client::TlsStream as crate::if_std::AsyncBufRead>::poll_fill_buf", "Argument[self].Reference", "ReturnValue.Reference", "taint", "manual"] |
There was a problem hiding this comment.
Nice try, but it doesn't help. Hopefully when we have support for MaD trait models, we can clean this stuff up.
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] | ||
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] |
There was a problem hiding this comment.
[nitpick] These two read rules only differ by .Reference. Consider consolidating into a single pattern (e.g., match Argument[self]) to reduce duplication and maintenance overhead.
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self].*", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self].*", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self].*", "Argument[0].Reference", "taint", "manual"] | |
| - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self].*", "Argument[1].Reference", "taint", "manual"] |
There was a problem hiding this comment.
There's missing data flow through certain implicit dereferences, when that's fixed we can get rid of the duplicate models.
paldepind
left a comment
There was a problem hiding this comment.
Looks good to me. I've created an internal issue for the problem about the same model not working for both function calls and method calls.
In reader.read(&mut buffer2) there is an implicit borrow of reader, so this is equivalent to (&reader).read(&mut buffer2). Therefore I think that the model that we actually want is the ones from 4d51a15 with Argument[self].Reference and not the ones with Argument[self].
Thanks, that's fantastic. I've just merged in a recent |
|
It turns out I needed an even more recent Ready for re-approval and merge. |
|
Thanks! |
Add models for
futures-io(traits, part offutures-rs), and forrustls+futures-rustls(which uses the traits and includes what seem like high value sources).Most of these work well, but the models for
poll_readandpoll_fill_bufaren't working reliably. I haven't been able to figure out what's wrong and I suspect it isn't an issue with the models themselves.There's also a fix of the test sink recognition logic that allows the test to find sinks in
sources/web_frameworks.rs, which also gives us a few results insources/web_frameworks.rsthat we should have been finding all along.