Repository navigation
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
QHelp previews: unified/ql/src/queries/security/CWE-094/UnsafeJsEval.qhelpJavaScript InjectionEvaluating JavaScript that contains a substring from a remote origin may lead to remote code execution. Code written by an attacker can execute unauthorized actions, including exfiltration of local data through a third party web service. RecommendationWhen loading JavaScript into a web view, evaluate only known, locally-defined source code. If part of the input comes from a remote source, do not inject it into the JavaScript code to be evaluated. Instead, send it to the web view as data using an API such as ExampleIn the following (bad) example, a call to let webview: WKWebView
let remoteData = try String(contentsOf: URL(string: "http://example.com/evil.json")!)
...
_ = try await webview.evaluateJavaScript("console.log(" + remoteData + ")") // BADIn the following (good) example, we sanitize the remote data by passing it using the let webview: WKWebView
let remoteData = try String(contentsOf: URL(string: "http://example.com/evil.json")!)
...
_ = try await webview.callAsyncJavaScript(
"console.log(data)",
arguments: ["data": remoteData], // GOOD
contentWorld: .page
)References
|
There was a problem hiding this comment.
🟡 Changes recommended
Incorrect Swift argument-label ordering and missing call-site variants leave code-injection sinks unrecognized, while overly broad source selection can cause false positives.
3 open issues
What changed in this PR
Adds JavaScript injection detection to unified Swift through the unified/swift/unsafe-js-eval query and models for Swift JavaScript execution APIs.
Changes:
- Introduces a path query and code-injection sink models.
- Documents unsafe interpolation and safer argument-based data passing.
- Adds regression fixtures and expected results, with known detection gaps marked inline.
| File | Description |
|---|---|
unified/ql/test/query-tests/security/CWE-094/UnsafeJsEval/UnsafeJsEval.swift |
Exercises JavaScript APIs, safe cases, and known gaps. |
unified/ql/test/query-tests/security/CWE-094/UnsafeJsEval/UnsafeJsEval.qlref |
Connects the query to inline-expectation testing. |
unified/ql/test/query-tests/security/CWE-094/UnsafeJsEval/UnsafeJsEval.expected |
Records expected alerts and taint paths. |
unified/ql/test/query-tests/security/CWE-094/UnsafeJsEval/CONSISTENCY/DataFlowConsistency.expected |
Captures data-flow consistency results. |
unified/ql/src/queries/security/CWE-094/UnsafeJsEvalGood.swift |
Demonstrates passing remote input as data. |
unified/ql/src/queries/security/CWE-094/UnsafeJsEvalBad.swift |
Demonstrates unsafe interpolation of remote input. |
unified/ql/src/queries/security/CWE-094/UnsafeJsEval.ql |
Defines the JavaScript injection path query. |
unified/ql/src/queries/security/CWE-094/UnsafeJsEval.qhelp |
Explains the risk and recommended mitigation. |
unified/ql/lib/ext/legacy-swift.model.yml |
Adds JavaScript execution sink models. |
Review effort: Max (auto)
| - ["", "WKWebView", true, "evaluateJavaScript(_:in:in:completionHandler:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKWebView", true, "evaluateJavaScript(_:in:contentWorld:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKWebView", true, "callAsyncJavaScript(_:arguments:in:in:completionHandler:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKWebView", true, "callAsyncJavaScript(_:arguments:in:contentWorld:)", "", "", "Argument[0]", "code-injection", "manual"] |
| - ["", "WKWebView", true, "evaluateJavaScript(_:in:contentWorld:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKWebView", true, "callAsyncJavaScript(_:arguments:in:in:completionHandler:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKWebView", true, "callAsyncJavaScript(_:arguments:in:contentWorld:)", "", "", "Argument[0]", "code-injection", "manual"] | ||
| - ["", "WKUserContentController", true, "addUserScript(_:)", "", "", "Argument[0]", "code-injection", "manual"] |
| * A taint configuration from taint sources to sinks for this query. | ||
| */ | ||
| module UnsafeJsEvalConfig implements DataFlow::ConfigSig { | ||
| predicate isSource(DataFlow::Node node) { Models::isSource(node, _) } |


Adds a
unified/swift/unsafe-js-evalquery for unified Swift. Done with the same agent skill as before, but a different model to test its versatility of that skill (MAI-Code-2.x1 high effort rather than GPT-6.1 Sol high effort). No problems there.... and no manual edits this time. We do fairly well on the QL test. There are some newly missing test results (and some that were missing even in the original analysis), addressing those will be follow-up work.
DCA run to follow.DCA LGTM.