Skip to content

Unified: Support property models with base-type match - #23048

Open
asgerf wants to merge 20 commits into
github:mainfrom
asgerf:unified/property-models-rebased
Open

asgerf wants to merge 20 commits into
github:mainfrom
asgerf:unified/property-models-rebased

Conversation

@asgerf

@asgerf asgerf commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Extends legacy MaD to support sources and sinks derived from property accesses, such as Process.arguments. Previously only calls and callables were matched.

Matching properties on name alone is too imprecise even at this stage, so this also makes a start on matching the base object against the inferred type. Types mentioned in a model are now tracked by static name binding and type inference. For example, when a function annotated with Process as the return type we can now track that, whereas previously we lacked a representative for it.

I'd like to take this a bit further and introduce a ClassLikeElement newtype that's the canonical representative for a class (think: union of non-extension class declaration and TypeSelector) and make APIs like ClassLikeDeclaration.resolve() and getAMemberIncludingExtensions based on that class instead. But to avoid a mega-PR and too many conflicts, I'm deferred that to a later PR.

The last commit documents a test failure that will pass once the ClassLikeElement refactoring is in.

The PR also limits taint reach to use local and remote sources, in particular to avoid inflating the number with things like string-length sources. Queries are also restricted to local and remote for this reason.

DCA run shows an increase in taint reach from 778->1058

@asgerf asgerf added the no-change-note-required This PR does not need a change note label Nov 9, 2026
@asgerf
asgerf requested a balanced review from Copilot November 9, 2026 08:04

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.

Note

Copilot was unable to run its full agentic suite in this review.

Copilot review overview

4 open issues
What changed in this PR

Updates unified Swift MaD/type-inference plumbing so property-based sources/sinks and model-only types are recognized, and adjusts security/library tests accordingly.

Changes:

  • Add model-driven property access selectors and a ModelType to support types referenced only in models-as-data (no declaration in DB).
  • Improve implicit-receiver inference and base-type inference for member accesses (including unqualified accesses).
  • Update multiple Swift query tests/expected outputs to reflect newly detected property sources/sinks.
File Description
unified/​ql/​test/​query-tests/​security/​CWE-078/​CommandInjection/​CommandInjection.swift Updates inline expectations where new sinks are now detected.
unified/​ql/​test/​query-tests/​security/​CWE-078/​CommandInjection/​CommandInjection.expected Adds expected results/edges/nodes for newly detected executableURL/arguments flows.
unified/​ql/​test/​query-tests/​security/​CWE-022/​PathInjection/​testPathInjection.swift Updates Realm configuration property expectations to alerts.
unified/​ql/​test/​query-tests/​security/​CWE-022/​PathInjection/​PathInjectionTest.expected Adds expected results/edges/nodes for new Realm fileURL/seedFilePath sinks.
unified/​ql/​test/​library-tests/​mad/​test.swift Expands MaD library test coverage for property sources/sinks, nested types, and implicit self.
unified/​ql/​test/​library-tests/​mad/​test.expected Updates expected MaD outputs to include new property sinks/sources.
unified/​ql/​test/​library-tests/​mad-builtins/​test.swift Adds a builtins-focused MaD test case without local stubs.
unified/​ql/​test/​library-tests/​mad-builtins/​test.qlref Wires the new builtins test to the existing MaD test query + postprocess.
unified/​ql/​test/​library-tests/​mad-builtins/​test.expected Adds expected outputs for the new builtins-based MaD test.
unified/​ql/​src/​queries/​security/​CWE-078/​CommandInjection.ql Narrows sources used by the command injection config.
unified/​ql/​src/​queries/​security/​CWE-022/​PathInjection.ql Narrows sources used by the path injection config.
unified/​ql/​lib/​codeql/​unified/​internal/​typeinference/​TypeMention.qll Allows type mentions to be resolved via ModelType selectors.
unified/​ql/​lib/​codeql/​unified/​internal/​typeinference/​TypeInference.qll Adds variable/base-type inference helpers and seeds inference from model-only constructor calls.
unified/​ql/​lib/​codeql/​unified/​internal/​typeinference/​Type.qll Introduces ModelType backed by MaD TypeSelectors.
unified/​ql/​lib/​codeql/​unified/​internal/​mad/​LegacyMaD.qll Adds property selectors, type selectors, and property source/sink extraction for MaD.
unified/​ql/​lib/​codeql/​unified/​internal/​StaticNameBinding.qll Extends name binding graph to support resolving MaD TypeSelectors; adds isTypeRef.
unified/​ql/​lib/​codeql/​unified/​internal/​ExprPositions.qll Switches type-context detection from getTypeFromRef existence to isTypeRef.
unified/​ql/​lib/​codeql/​unified/​internal/​AnalysisQuality.qll Narrows sources used by taint reach quality analysis config.

Review effort: Lite

@asgerf

asgerf commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

@asgerf
asgerf marked this pull request as ready for review November 9, 2026 10:08
@asgerf
asgerf requested a review from a team as a code owner November 9, 2026 10:08
private predicate propertyAccessSelector(MemberAccess access, ClassLikeDeclaration cls, string name) {
name = access.getMemberName() and
name = any(Selector s).getPropertyName() and
not access = any(CallExpr call).getCallee() and

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.

Could a property not hold a closure value?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. I suppose this line is an optimization that's only valid because we know we can't derive meaningful sources or sinks when a property access appears in callee position.

}

/** Gets the declaration of this type, if any. */
ClassLikeDeclaration getDeclaration() { result.getQualifiedName() = this }

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.

Should we avoid generating synthetic namebinding nodes and types in this case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A later commit restricts types to avoid duplicate representatives for the type.

For static name binding it would lead to negative recursion as getQualifiedName() depends on extension-resolution (which is beneficial, albeit only in rare situations).

We could use the syntactic qualified name if we really wanted to cut that dependency, but I suspect we'll want to be able to depend on static name binding here even more in the future, e.g. when we want types to be qualified by their module (e.g Foundation.URL instead of URL).

Avoid inflating the numebr with string-length sources and similar.
This enables type inference to track these types because they now have a synthetic definition.
ClassLikeDeclaration is now a static member
Some more tests in mad-builtins pass because they now work without stub declarations
This is needed to make TypeMention include references to a type from a model
Avoid creating ModelType when a ClassDeclarationType exists
If an extension resolving to a TypeSelector existed, we'd fail to create a ModelType for it.
This addresses a very niche concern from Copilot that, if a value
resolves to both a value (e.g. field) and a model type, then it should
not be seen as being in type context. It's very difficult to see this
matter in practice but why not.
@asgerf
asgerf force-pushed the unified/property-models-rebased branch from 64e164e to a41f207 Compare November 12, 2026 11:23

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

no-change-note-required This PR does not need a change note Unified

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants