Skip to content

Commit 40903a9

Browse files
authored
Merge pull request #18975 from Napalys/js/tanstack_angular
JS: Update Angular Client Request's with API graph and `Tanstack` Angular modeling
2 parents a5101bd + f867e0f commit 40903a9

File tree

5 files changed

+74
-2
lines changed

5 files changed

+74
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added support for the `@tanstack/angular-query-experimental` package.
5+
* Improved support for the `@angular/common/http` package, detecting outgoing HTTP requests in more cases.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/javascript-all
4+
extensible: summaryModel
5+
data:
6+
- ["@tanstack/angular-query-experimental", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "taint"]
7+
- ["@tanstack/angular-query", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "taint"]

javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,16 @@ module Angular2 {
190190
result.hasUnderlyingType("@angular/common/http", "HttpClient")
191191
}
192192

193+
/** Gets a reference to an `HttpClient` object using the API graph. */
194+
API::Node httpClientApiNode() { result = API::Node::ofType("@angular/common/http", "HttpClient") }
195+
193196
private class AngularClientRequest extends ClientRequest::Range, DataFlow::MethodCallNode {
194197
int argumentOffset;
195198

196199
AngularClientRequest() {
197-
this = httpClient().getAMethodCall("request") and argumentOffset = 1
200+
this = httpClientApiNode().getMember("request").getACall() and argumentOffset = 1
198201
or
199-
this = httpClient().getAMethodCall() and
202+
this = httpClientApiNode().getAMember().getACall() and
200203
not this.getMethodName() = "request" and
201204
argumentOffset = 0
202205
}

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXssWithResponseThreat/Xss.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#select
22
| test.jsx:27:29:27:32 | data | test.jsx:5:28:5:63 | fetch(" ... ntent") | test.jsx:27:29:27:32 | data | Cross-site scripting vulnerability due to $@. | test.jsx:5:28:5:63 | fetch(" ... ntent") | user-provided value |
3+
| test.ts:21:57:21:76 | response.description | test.ts:8:9:8:79 | this.#h ... query') | test.ts:21:57:21:76 | response.description | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
4+
| test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | test.ts:8:9:8:79 | this.#h ... query') | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
35
| testReactRelay.tsx:7:43:7:58 | commentData.text | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:7:43:7:58 | commentData.text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | user-provided value |
46
| testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | user-provided value |
57
| testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | user-provided value |
@@ -20,6 +22,15 @@ edges
2022
| test.jsx:6:24:6:38 | response.json() | test.jsx:6:18:6:38 | await r ... .json() | provenance | |
2123
| test.jsx:7:12:7:15 | data | test.jsx:15:11:17:5 | data | provenance | |
2224
| test.jsx:15:11:17:5 | data | test.jsx:27:29:27:32 | data | provenance | |
25+
| test.ts:8:9:8:79 | this.#h ... query') | test.ts:20:28:20:35 | response | provenance | |
26+
| test.ts:20:28:20:35 | response | test.ts:21:57:21:64 | response | provenance | |
27+
| test.ts:20:28:20:35 | response | test.ts:24:43:24:50 | response | provenance | |
28+
| test.ts:20:28:20:35 | response | test.ts:24:67:24:74 | response | provenance | |
29+
| test.ts:21:57:21:64 | response | test.ts:21:57:21:76 | response.description | provenance | |
30+
| test.ts:24:43:24:50 | response | test.ts:24:43:24:55 | response.name | provenance | |
31+
| test.ts:24:43:24:55 | response.name | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | provenance | |
32+
| test.ts:24:67:24:74 | response | test.ts:24:67:24:84 | response.owner.bio | provenance | |
33+
| test.ts:24:67:24:84 | response.owner.bio | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | provenance | |
2334
| testReactRelay.tsx:5:9:5:52 | commentData | testReactRelay.tsx:7:43:7:53 | commentData | provenance | |
2435
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:5:9:5:52 | commentData | provenance | |
2536
| testReactRelay.tsx:7:43:7:53 | commentData | testReactRelay.tsx:7:43:7:58 | commentData.text | provenance | |
@@ -56,6 +67,15 @@ nodes
5667
| test.jsx:7:12:7:15 | data | semmle.label | data |
5768
| test.jsx:15:11:17:5 | data | semmle.label | data |
5869
| test.jsx:27:29:27:32 | data | semmle.label | data |
70+
| test.ts:8:9:8:79 | this.#h ... query') | semmle.label | this.#h ... query') |
71+
| test.ts:20:28:20:35 | response | semmle.label | response |
72+
| test.ts:21:57:21:64 | response | semmle.label | response |
73+
| test.ts:21:57:21:76 | response.description | semmle.label | response.description |
74+
| test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | semmle.label | `<h2>${ ... o}</p>` |
75+
| test.ts:24:43:24:50 | response | semmle.label | response |
76+
| test.ts:24:43:24:55 | response.name | semmle.label | response.name |
77+
| test.ts:24:67:24:74 | response | semmle.label | response |
78+
| test.ts:24:67:24:84 | response.owner.bio | semmle.label | response.owner.bio |
5979
| testReactRelay.tsx:5:9:5:52 | commentData | semmle.label | commentData |
6080
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | semmle.label | useFrag ... entRef) |
6181
| testReactRelay.tsx:7:43:7:53 | commentData | semmle.label | commentData |
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'
2+
import { HttpClient } from '@angular/common/http'
3+
4+
class ServiceOrComponent {
5+
query = injectQuery(() => ({
6+
queryKey: ['repoData'],
7+
queryFn: () =>
8+
this.#http.get<Response>('https://api.github.com/repos/tanstack/query'), // $ Source
9+
}))
10+
11+
#http: {
12+
get: <T>(url: string) => Promise<T>
13+
};
14+
15+
constructor(http: HttpClient) {
16+
this.#http = http;
17+
}
18+
19+
displayRepoDetails() {
20+
this.query.data.then(response => {
21+
document.getElementById('repoInfo').innerHTML = response.description; // $ Alert
22+
23+
const detailsElement = document.createElement('div');
24+
detailsElement.innerHTML = `<h2>${response.name}</h2><p>${response.owner.bio}</p>`; // $ Alert
25+
document.body.appendChild(detailsElement);
26+
});
27+
}
28+
}
29+
30+
interface Response {
31+
name: string;
32+
description: string;
33+
stargazers_count: number;
34+
owner: {
35+
bio: string;
36+
}
37+
}

0 commit comments

Comments
 (0)