@appland/scanner 1.40.1 → 1.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -39
- package/built/cli/ci/command.js +1 -1
- package/built/cli/ci/command.js.map +1 -1
- package/built/cli/upload/command.js +1 -1
- package/built/cli/upload/command.js.map +1 -1
- package/built/eventUtil.js +61 -0
- package/built/eventUtil.js.map +1 -0
- package/built/integration/appland/upload.js +2 -3
- package/built/integration/appland/upload.js.map +1 -1
- package/built/ruleChecker.js +4 -3
- package/built/ruleChecker.js.map +1 -1
- package/built/rules/authzBeforeAuthn.js +6 -0
- package/built/rules/authzBeforeAuthn.js.map +1 -1
- package/built/rules/circularDependency.js +3 -0
- package/built/rules/circularDependency.js.map +1 -1
- package/built/rules/deserializationOfUntrustedData.js +6 -0
- package/built/rules/deserializationOfUntrustedData.js.map +1 -1
- package/built/rules/http500.js +6 -0
- package/built/rules/http500.js.map +1 -1
- package/built/rules/illegalPackageDependency.js +6 -0
- package/built/rules/illegalPackageDependency.js.map +1 -1
- package/built/rules/incompatibleHttpClientRequest.js +6 -0
- package/built/rules/incompatibleHttpClientRequest.js.map +1 -1
- package/built/rules/insecureCompare.js +3 -0
- package/built/rules/insecureCompare.js.map +1 -1
- package/built/rules/jobNotCancelled.js +3 -0
- package/built/rules/jobNotCancelled.js.map +1 -1
- package/built/rules/lib/parseRuleDescription.js +18 -0
- package/built/rules/lib/parseRuleDescription.js.map +1 -0
- package/built/rules/logoutWithoutSessionReset.js +6 -0
- package/built/rules/logoutWithoutSessionReset.js.map +1 -1
- package/built/rules/missingAuthentication.js +6 -0
- package/built/rules/missingAuthentication.js.map +1 -1
- package/built/rules/missingContentType.js +6 -0
- package/built/rules/missingContentType.js.map +1 -1
- package/built/rules/nPlusOneQuery.js +6 -0
- package/built/rules/nPlusOneQuery.js.map +1 -1
- package/built/rules/queryFromInvalidPackage.js +6 -0
- package/built/rules/queryFromInvalidPackage.js.map +1 -1
- package/built/rules/queryFromView.js +6 -0
- package/built/rules/queryFromView.js.map +1 -1
- package/built/rules/rpcWithoutCircuitBreaker.js +6 -0
- package/built/rules/rpcWithoutCircuitBreaker.js.map +1 -1
- package/built/rules/saveWithoutValidation.js +6 -0
- package/built/rules/saveWithoutValidation.js.map +1 -1
- package/built/rules/secretInLog.js +3 -0
- package/built/rules/secretInLog.js.map +1 -1
- package/built/rules/slowFunctionCall.js +6 -0
- package/built/rules/slowFunctionCall.js.map +1 -1
- package/built/rules/slowHttpServerRequest.js +6 -0
- package/built/rules/slowHttpServerRequest.js.map +1 -1
- package/built/rules/slowQuery.js +6 -0
- package/built/rules/slowQuery.js.map +1 -1
- package/built/rules/tooManyJoins.js +6 -0
- package/built/rules/tooManyJoins.js.map +1 -1
- package/built/rules/tooManyUpdates.js +6 -0
- package/built/rules/tooManyUpdates.js.map +1 -1
- package/built/rules/unbatchedMaterializedQuery.js +6 -0
- package/built/rules/unbatchedMaterializedQuery.js.map +1 -1
- package/built/rules/updateInGetRequest.js +6 -0
- package/built/rules/updateInGetRequest.js.map +1 -1
- package/doc/architecture.md +48 -0
- package/doc/labels/audit.md +7 -0
- package/doc/labels/dao.materialize.md +12 -0
- package/doc/labels/deserialize.safe.md +9 -0
- package/doc/labels/deserialize.unsafe.md +12 -0
- package/doc/labels/http.session.clear.md +7 -0
- package/doc/labels/job.cancel.md +11 -0
- package/doc/labels/job.create.md +13 -0
- package/doc/labels/log.md +12 -0
- package/doc/labels/public.md +8 -0
- package/doc/labels/rpc.circuit_breaker.md +16 -0
- package/doc/labels/sanitize.md +29 -0
- package/doc/labels/secret.md +11 -0
- package/doc/labels/security.authentication.md +10 -0
- package/doc/labels/security.authorization.md +9 -0
- package/doc/labels/security.logout.md +9 -0
- package/doc/labels/string.equals.md +18 -0
- package/doc/rules/authzBeforeAuthn.md +47 -0
- package/doc/rules/circularDependency.md +57 -0
- package/doc/rules/deserializationOfUntrustedData.md +55 -0
- package/doc/rules/http500.md +36 -0
- package/doc/rules/illegalPackageDependency.md +50 -0
- package/doc/rules/incompatibleHttpClientRequest.md +35 -0
- package/doc/rules/insecureCompare.md +59 -0
- package/doc/rules/jobNotCancelled.md +49 -0
- package/doc/rules/logoutWithoutSessionReset.md +40 -0
- package/doc/rules/missingAuthentication.md +59 -0
- package/doc/rules/missingContentType.md +33 -0
- package/doc/rules/nPlusOneQuery.md +52 -0
- package/doc/rules/queryFromInvalidPackage.md +45 -0
- package/doc/rules/queryFromView.md +42 -0
- package/doc/rules/rpcWithoutCircuitBreaker.md +44 -0
- package/doc/rules/saveWithoutValidation.md +33 -0
- package/doc/rules/secretInLog.md +49 -0
- package/doc/rules/slowFunctionCall.md +39 -0
- package/doc/rules/slowHttpServerRequest.md +34 -0
- package/doc/rules/slowQuery.md +33 -0
- package/doc/rules/tooManyJoins.md +40 -0
- package/doc/rules/tooManyUpdates.md +46 -0
- package/doc/rules/unbatchedMaterializedQuery.md +54 -0
- package/doc/rules/updateInGetRequest.md +44 -0
- package/package.json +3 -2
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: missing-authentication
|
|
3
|
+
name: Missing authentication
|
|
4
|
+
title: Unauthenticated HTTP server request
|
|
5
|
+
references:
|
|
6
|
+
CWE-306: https://cwe.mitre.org/data/definitions/306.html
|
|
7
|
+
impactDomain: Security
|
|
8
|
+
labels:
|
|
9
|
+
- public
|
|
10
|
+
- security.authentication
|
|
11
|
+
scope: http_server_request
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
An HTTP server request is missing authentication. In this case, the request may be serving assets
|
|
15
|
+
that should be protected by authentication - but no authentication is actually happening.
|
|
16
|
+
|
|
17
|
+
### Rule logic
|
|
18
|
+
|
|
19
|
+
This rule checks all HTTP server requests that satisfy the following conditions:
|
|
20
|
+
|
|
21
|
+
- HTTP status code is `< 300`
|
|
22
|
+
- Matches include and exclude lists of content type (by default, these are empty).
|
|
23
|
+
|
|
24
|
+
For each matching request, any event that satisfies either of these conditions will satisfy the rule:
|
|
25
|
+
|
|
26
|
+
1. Has label `public`.
|
|
27
|
+
2. Has label `security.authentication`, and returns a truthy value.
|
|
28
|
+
|
|
29
|
+
### Notes
|
|
30
|
+
|
|
31
|
+
If a request does not require an authenticated user (e.g. because it contains completely public
|
|
32
|
+
information), then this rule can be satisfied by calling any function labeled `public`.
|
|
33
|
+
|
|
34
|
+
If the `security.authentication` event returns a falsey value (`false`, `null`, etc), then
|
|
35
|
+
authentication is assumed to be denied, and the rule is not satisfied.
|
|
36
|
+
|
|
37
|
+
### Resolution
|
|
38
|
+
|
|
39
|
+
If the request is designed to be public, and the omission of authentication is intentionaly, modify
|
|
40
|
+
the code so that it calls a function labeled `public`.
|
|
41
|
+
|
|
42
|
+
Otherwise, modify the code so that it calls a function labeled `security.authentication` which
|
|
43
|
+
returns a truthy result (for example, a User object).
|
|
44
|
+
|
|
45
|
+
### Options
|
|
46
|
+
|
|
47
|
+
- `includeContentTypes: ` [MatchPatternConfig](/docs/analysis/match-pattern-config.html)`[]`.
|
|
48
|
+
Default: empty - including all content types.
|
|
49
|
+
- `excludeContentTypes: ` [MatchPatternConfig](/docs/analysis/match-pattern-config.html)`[]`.
|
|
50
|
+
Default: empty - excluding no content types.
|
|
51
|
+
|
|
52
|
+
### Examples
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
- rule: missingAuthentication
|
|
56
|
+
properties:
|
|
57
|
+
includeContentTypes:
|
|
58
|
+
- match: ^application/json
|
|
59
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: missing-content-type
|
|
3
|
+
name: Missing content type
|
|
4
|
+
title: HTTP server request without a Content-Type header
|
|
5
|
+
impactDomain: Stability
|
|
6
|
+
scope: http_server_request
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Finds HTTP server requests that don't provide a `Content-Type` header in the response.
|
|
10
|
+
|
|
11
|
+
### Rule logic
|
|
12
|
+
|
|
13
|
+
Every HTTP server request is checked. If the status code indicates redirect or "No content", then
|
|
14
|
+
the rule passes. Otherwise, a finding is issued if the response is missing a `Content-Type` header.
|
|
15
|
+
|
|
16
|
+
### Notes
|
|
17
|
+
|
|
18
|
+
When a response is missing the `Content-Type` header, it's unclear to clients how to handle the
|
|
19
|
+
response data. Bugs are likely to result.
|
|
20
|
+
|
|
21
|
+
### Resolution
|
|
22
|
+
|
|
23
|
+
Provide a `Content-Type` in the response.
|
|
24
|
+
|
|
25
|
+
### Options
|
|
26
|
+
|
|
27
|
+
None
|
|
28
|
+
|
|
29
|
+
### Examples
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
- rule: missingContentType
|
|
33
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: n-plus-one-query
|
|
3
|
+
name: N plus one query
|
|
4
|
+
title: N plus 1 SQL query
|
|
5
|
+
references:
|
|
6
|
+
CWE-1073: https://cwe.mitre.org/data/definitions/1073.html
|
|
7
|
+
impactDomain: Performance
|
|
8
|
+
scope: command
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Finds occurrences of a query being repeated within a loop.
|
|
13
|
+
|
|
14
|
+
### Rule logic
|
|
15
|
+
|
|
16
|
+
Within each command, SQL queries are normalized, grouped, and counted.
|
|
17
|
+
|
|
18
|
+
If the number of duplicate instances of a normalized query exceeds the threshold, it's reported as a
|
|
19
|
+
finding.
|
|
20
|
+
|
|
21
|
+
### Notes
|
|
22
|
+
|
|
23
|
+
N plus one queries typically occur when a
|
|
24
|
+
[data access object (DAO)](https://en.wikipedia.org/wiki/Data_access_object) has a one-to-many or
|
|
25
|
+
many-to-many relationship, and the relationship is enumerated within a loop. The DAO will issue a
|
|
26
|
+
separate query to fetch each related record. If the number of related objects is large, or if each
|
|
27
|
+
one is fairly expensive to fetch, application performance suffers.
|
|
28
|
+
|
|
29
|
+
### Resolution
|
|
30
|
+
|
|
31
|
+
DAO libraries typically offer a feature called "eager loading". For example:
|
|
32
|
+
|
|
33
|
+
- [ActiveRecord](https://news.learnenough.com/eager-loading)
|
|
34
|
+
- [Django ORM](https://docs.djangoproject.com/en/4.0/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it)
|
|
35
|
+
- [Hibernate](https://docs.jboss.org/hibernate/orm/5.3/javadocs/org/hibernate/jpamodelgen/xml/jaxb/FetchType.html)
|
|
36
|
+
|
|
37
|
+
Enable eager loading on the association in question to fetch the data efficiently, without repeated,
|
|
38
|
+
identical queries.
|
|
39
|
+
|
|
40
|
+
### Options
|
|
41
|
+
|
|
42
|
+
- `warningLimit` Threshold for reporting a warning. Default: 5.
|
|
43
|
+
- `errorLimit` Threshold for reporting an error. Default: 10.
|
|
44
|
+
|
|
45
|
+
### Examples
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
- rule: nPlusOneQuery
|
|
49
|
+
parameters:
|
|
50
|
+
warningLimit: 5
|
|
51
|
+
errorLimit: 10
|
|
52
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: query-from-invalid-package
|
|
3
|
+
name: Query from invalid package
|
|
4
|
+
title: Queries from invalid packages
|
|
5
|
+
references:
|
|
6
|
+
CWE-1057: https://cwe.mitre.org/data/definitions/1057.html
|
|
7
|
+
impactDomain: Maintainability
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Ensures that SQL queries are made only from an approved list of packages. This helps to make the
|
|
11
|
+
code more maintainable by encapsulating access to the database.
|
|
12
|
+
|
|
13
|
+
### Notes
|
|
14
|
+
|
|
15
|
+
When too many packages are performing direct SQL queries, it's very hard to keep the code modular.
|
|
16
|
+
The result is a lack of coherent design and degredation in maintainability.
|
|
17
|
+
|
|
18
|
+
### Rule logic
|
|
19
|
+
|
|
20
|
+
All functions which make SQL queries are inspected. Each one must match one of the
|
|
21
|
+
`allowedPackages`.
|
|
22
|
+
|
|
23
|
+
### Resolution
|
|
24
|
+
|
|
25
|
+
The code which is making the direct query should be refactored to use the database through one of
|
|
26
|
+
the allowed packages.
|
|
27
|
+
|
|
28
|
+
### Options
|
|
29
|
+
|
|
30
|
+
- `allowedPackages: `[MatchPatternConfig](/docs/analysis/match-pattern-config.html)`[]`. Packages
|
|
31
|
+
which are allowed to make queries. Required.
|
|
32
|
+
- `allowedQueries: `[MatchPatternConfig](/docs/analysis/match-pattern-config.html)`[]`. Queries which
|
|
33
|
+
are allowed from anywhere. Default:
|
|
34
|
+
`[/\bBEGIN\b/i, /\bCOMMIT\b/i, /\bROLLBACK\b/i, /\bRELEASE\b/i, /\bSAVEPOINT\b/i]`.
|
|
35
|
+
|
|
36
|
+
### Examples
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- rule: queryFromInvalidPackage
|
|
40
|
+
properties:
|
|
41
|
+
callerPackages:
|
|
42
|
+
- equal: actionpack
|
|
43
|
+
calleePackage:
|
|
44
|
+
equal: app/controllers
|
|
45
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: query-from-view
|
|
3
|
+
name: Query from view
|
|
4
|
+
title: Queries from view
|
|
5
|
+
references:
|
|
6
|
+
CWE-1057: https://cwe.mitre.org/data/definitions/1057.html
|
|
7
|
+
impactDomain: Maintainability
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Ensures that SQL queries are not performed directly from the view layer. This helps to make the code
|
|
11
|
+
more maintainable by encapsulating access to the database.
|
|
12
|
+
|
|
13
|
+
### Notes
|
|
14
|
+
|
|
15
|
+
Performing SQL queries directly from the view layer introduces several maintainability concerns:
|
|
16
|
+
|
|
17
|
+
1. View logic is tied to the server, and cannot be refactored to the client side.
|
|
18
|
+
2. Database interactions are harder to test, because they depend on details of the view
|
|
19
|
+
implementation.
|
|
20
|
+
3. Performance can be adversely and unexpectedly affected by minor changes to the view.
|
|
21
|
+
|
|
22
|
+
### Rule logic
|
|
23
|
+
|
|
24
|
+
Each query is tested to see if it has an ancestor event with the view label.
|
|
25
|
+
|
|
26
|
+
### Resolution
|
|
27
|
+
|
|
28
|
+
Data objects which are passed to the view layer for rendering should not have access to the
|
|
29
|
+
database. Disable database access in some way, or transfer data from DAO objects into plain old
|
|
30
|
+
structs.
|
|
31
|
+
|
|
32
|
+
### Options
|
|
33
|
+
|
|
34
|
+
- `forbiddenLabel`. Label which identifies the view layer. Default: `mvc.template`.
|
|
35
|
+
|
|
36
|
+
### Examples
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- rule: queryFromView
|
|
40
|
+
properties:
|
|
41
|
+
forbiddenLabel: mvc.template
|
|
42
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: rpc-without-circuit-breaker
|
|
3
|
+
name: RPC without circuit breaker
|
|
4
|
+
title: RPC without circuit breaker
|
|
5
|
+
impactDomain: Stability
|
|
6
|
+
labels:
|
|
7
|
+
- rpc.circuit_breaker
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Identifies HTTP client requests which do not utilize a
|
|
11
|
+
[circuit breaker](https://martinfowler.com/bliki/CircuitBreaker.html).
|
|
12
|
+
|
|
13
|
+
### Rule logic
|
|
14
|
+
|
|
15
|
+
Each HTTP client request is expected to have a descendant labeled with the expected label.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
|
|
19
|
+
Use the circuit breaker pattern in microservices architecture to make system behavior more
|
|
20
|
+
predictable when a service becomes overloaded or unavailable.
|
|
21
|
+
|
|
22
|
+
### Resolution
|
|
23
|
+
|
|
24
|
+
Utilize a circuit breaker library - your organization may have a specific preference.
|
|
25
|
+
|
|
26
|
+
Some examples:
|
|
27
|
+
|
|
28
|
+
- [Hystrix (Java)](https://github.com/Netflix/Hystrix/wiki/How-it-Works#CircuitBreaker)
|
|
29
|
+
- [CircuitBox (Ruby)](https://github.com/yammer/circuitbox)
|
|
30
|
+
- [Semian (Ruby)](https://github.com/Shopify/semian#circuit-breaker)
|
|
31
|
+
- [pybreaker (Python)](https://github.com/danielfm/pybreaker)
|
|
32
|
+
|
|
33
|
+
### Options
|
|
34
|
+
|
|
35
|
+
- `expectedLabel`. Label which identifies the circuit breaker function. Default:
|
|
36
|
+
`rpc.circuit_breaker`.
|
|
37
|
+
|
|
38
|
+
### Examples
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
- rule: rpcWithoutCircuitBreaker
|
|
42
|
+
properties:
|
|
43
|
+
expectedLabel: rpc.circuit_breaker
|
|
44
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: save-without-validation
|
|
3
|
+
name: Save without validation
|
|
4
|
+
title: Save without validation
|
|
5
|
+
references:
|
|
6
|
+
CWE-20: https://cwe.mitre.org/data/definitions/20.html
|
|
7
|
+
impactDomain: Stability
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Ensures that data saved by data access object is validated first.
|
|
11
|
+
|
|
12
|
+
### Rule logic
|
|
13
|
+
|
|
14
|
+
Finds events whose method name is `save` or `save!`. Then verifies that each of these events has a
|
|
15
|
+
descendant whose method name is `valid?` or `validate!`.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
|
|
19
|
+
In a future revision, this rule will be refactored to use labels rather than method names.
|
|
20
|
+
|
|
21
|
+
### Resolution
|
|
22
|
+
|
|
23
|
+
Ensure that data is validated before being saved; for example, using a `before_save` hook.
|
|
24
|
+
|
|
25
|
+
### Options
|
|
26
|
+
|
|
27
|
+
None
|
|
28
|
+
|
|
29
|
+
### Examples
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
- rule: saveWithoutValidation
|
|
33
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: secret-in-log
|
|
3
|
+
name: Secret in log
|
|
4
|
+
title: Secret in log
|
|
5
|
+
references:
|
|
6
|
+
CWE-532: https://cwe.mitre.org/data/definitions/532.html
|
|
7
|
+
impactDomain: Security
|
|
8
|
+
labels:
|
|
9
|
+
- secret
|
|
10
|
+
- log
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Identifies when a known or assumed secret is written to a log. Logs are often transported into other
|
|
14
|
+
systems that are treated with lesser security - such as backups. Therefore, secrets written into log
|
|
15
|
+
files are more likely to be leaked or discovered by cyber-attackers.
|
|
16
|
+
|
|
17
|
+
### Rule logic
|
|
18
|
+
|
|
19
|
+
Operation of this rule depends on two labels: `secret` and `log`. A function labeled `secret` is
|
|
20
|
+
assumed to return a secret value - this rule keeps a running tally of all the secrets created in an
|
|
21
|
+
AppMap. When a function labeled `log` is called, the rule looks at the log message, and checks
|
|
22
|
+
whether any of the known secrets are in it.
|
|
23
|
+
|
|
24
|
+
The log message is also tested against a list of known regular expressions that are likely to match
|
|
25
|
+
secrets.
|
|
26
|
+
|
|
27
|
+
### Notes
|
|
28
|
+
|
|
29
|
+
Be sure and apply the `secret` label to any function in your code base that generates a secret (such
|
|
30
|
+
as encryption keys, user tokens, API keys, reset tokens, etc.).
|
|
31
|
+
|
|
32
|
+
### Resolution
|
|
33
|
+
|
|
34
|
+
If the log message is written by code that you control, the simplest resolution is to remove the log
|
|
35
|
+
statement - or to remove the secret from the log message.
|
|
36
|
+
|
|
37
|
+
If the log message is not controlled by you (it's generated by a framework), your choices are more
|
|
38
|
+
limited. You could open a pull request with the framework, or you can change the log level to
|
|
39
|
+
suppress the offending message.
|
|
40
|
+
|
|
41
|
+
### Options
|
|
42
|
+
|
|
43
|
+
None
|
|
44
|
+
|
|
45
|
+
### Examples
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
- rule: secretInLog
|
|
49
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: slow-function-call
|
|
3
|
+
name: Slow function call
|
|
4
|
+
title: Slow function call
|
|
5
|
+
impactDomain: Performance
|
|
6
|
+
scope: root
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Ensures that function elapsed time does not exceed a threshold.
|
|
10
|
+
|
|
11
|
+
### Rule logic
|
|
12
|
+
|
|
13
|
+
Checks all configured functions to see if the elapsed time exceeds the configured threshold.
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
|
|
17
|
+
This rule is most useful when applied to code that is specifically designed to test application
|
|
18
|
+
performance.
|
|
19
|
+
|
|
20
|
+
### Resolution
|
|
21
|
+
|
|
22
|
+
Optimize the function elapsed time using a profiler, SQL tuning, etc.
|
|
23
|
+
|
|
24
|
+
### Options
|
|
25
|
+
|
|
26
|
+
- `functions: `[MatchPatternConfig](/docs/analysis/match-pattern-config.html)`[]` list of functions
|
|
27
|
+
to check. Required.
|
|
28
|
+
- `timeAllowed` max time (in seconds) allowed for the function.
|
|
29
|
+
|
|
30
|
+
### Examples
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
- rule: slowFunctionCall
|
|
34
|
+
properties:
|
|
35
|
+
timeAllowed: 0.25
|
|
36
|
+
functions:
|
|
37
|
+
- match: ^app/models
|
|
38
|
+
- match: ^app/jobs
|
|
39
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: slow-http-server-request
|
|
3
|
+
name: Slow HTTP server request
|
|
4
|
+
title: Slow HTTP server request
|
|
5
|
+
impactDomain: Performance
|
|
6
|
+
scope: http_server_request
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Ensures that HTTP server request elapsed time does not exceed a threshold.
|
|
10
|
+
|
|
11
|
+
### Rule logic
|
|
12
|
+
|
|
13
|
+
Checks HTTP server requests to see if the elapsed time exceeds the configured threshold.
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
|
|
17
|
+
This rule is most useful when applied to code that is specifically designed to test application
|
|
18
|
+
performance.
|
|
19
|
+
|
|
20
|
+
### Resolution
|
|
21
|
+
|
|
22
|
+
Optimize the request elapsed time using a profiler, SQL tuning, etc.
|
|
23
|
+
|
|
24
|
+
### Options
|
|
25
|
+
|
|
26
|
+
- `timeAllowed` max time (in seconds) allowed for the request.
|
|
27
|
+
|
|
28
|
+
### Examples
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
- rule: slowHttpServerRequest
|
|
32
|
+
properties:
|
|
33
|
+
timeAllowed: 0.25
|
|
34
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: slow-query
|
|
3
|
+
name: Slow query
|
|
4
|
+
title: Slow SQL query
|
|
5
|
+
impactDomain: Performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Ensures that SQL query elapsed time does not exceed a threshold.
|
|
9
|
+
|
|
10
|
+
### Rule logic
|
|
11
|
+
|
|
12
|
+
Checks all configured queries to see if the elapsed time exceeds the configured threshold.
|
|
13
|
+
|
|
14
|
+
### Notes
|
|
15
|
+
|
|
16
|
+
This rule is most useful when applied to code that is specifically designed to test application
|
|
17
|
+
performance.
|
|
18
|
+
|
|
19
|
+
### Resolution
|
|
20
|
+
|
|
21
|
+
Optimize the elapsed time using SQL tuning.
|
|
22
|
+
|
|
23
|
+
### Options
|
|
24
|
+
|
|
25
|
+
- `timeAllowed` max time (in seconds) allowed for the query.
|
|
26
|
+
|
|
27
|
+
### Examples
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- rule: slowQuery
|
|
31
|
+
properties:
|
|
32
|
+
timeAllowed: 0.25
|
|
33
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: too-many-joins
|
|
3
|
+
name: Too many joins
|
|
4
|
+
title: Too many joins
|
|
5
|
+
references:
|
|
6
|
+
CWE-1049: https://cwe.mitre.org/data/definitions/1049.html
|
|
7
|
+
impactDomain: Performance
|
|
8
|
+
scope: command
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Verifies that the number of joins in SQL queries does not exceed a threshold.
|
|
12
|
+
|
|
13
|
+
### Rule logic
|
|
14
|
+
|
|
15
|
+
Counts the number of joins in each SQL query. If the count exceeds the configured threshold, a
|
|
16
|
+
finding is reported.
|
|
17
|
+
|
|
18
|
+
### Notes
|
|
19
|
+
|
|
20
|
+
Queries with too many joins often have poor or unpredictable performance.
|
|
21
|
+
|
|
22
|
+
### Resolution
|
|
23
|
+
|
|
24
|
+
Having multiple joins may be legitimate - but it is a situation that merits a closer look,
|
|
25
|
+
especially when the query is generated by an ORM.
|
|
26
|
+
|
|
27
|
+
Take a look at a query plan from a database that has a realistically high volume of data, and verify
|
|
28
|
+
that the query can be executed efficiently.
|
|
29
|
+
|
|
30
|
+
### Options
|
|
31
|
+
|
|
32
|
+
- `warningLimit` the maximum number of joins allowed.
|
|
33
|
+
|
|
34
|
+
### Examples
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
- rule: tooManyJoins
|
|
38
|
+
properties:
|
|
39
|
+
warningLimit: 5
|
|
40
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: too-many-updates
|
|
3
|
+
name: Too many updates
|
|
4
|
+
title: Too many SQL and RPC updates performed in one command
|
|
5
|
+
references:
|
|
6
|
+
CWE-1048: https://cwe.mitre.org/data/definitions/1048.html
|
|
7
|
+
impactDomain: Maintainability
|
|
8
|
+
scope: command
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Verifies that the number of SQL and RPC updates performed by a command does not exceed a threshold.
|
|
12
|
+
|
|
13
|
+
### Rule logic
|
|
14
|
+
|
|
15
|
+
Counts the number of SQL and RPC updates in each command. A SQL update is any `INSERT` or `UPDATE`
|
|
16
|
+
query. An RPC update is an HTTP client request that uses `PUT`, `POST`, or `PATCH`.
|
|
17
|
+
|
|
18
|
+
If the number of updates exceeds the threshold, a finding is reported.
|
|
19
|
+
|
|
20
|
+
### Notes
|
|
21
|
+
|
|
22
|
+
As a codebase evolves, sometimes a request can start to make more and more SQL and RPC updates.There
|
|
23
|
+
are several negative repercussions of this:
|
|
24
|
+
|
|
25
|
+
1. It's no longer clear to a developer what the primary responsibility of the command is.
|
|
26
|
+
2. The command becomes more likely to fail - resulting in a rollback of all the updates, or possibly
|
|
27
|
+
leaving the system in an inconsistent state.
|
|
28
|
+
3. The performance of the command degrades as it does more and more work.
|
|
29
|
+
|
|
30
|
+
### Resolution
|
|
31
|
+
|
|
32
|
+
Consider refactoring the command into multiple commands.
|
|
33
|
+
|
|
34
|
+
Schedule a job to perform some of the work offline.
|
|
35
|
+
|
|
36
|
+
### Options
|
|
37
|
+
|
|
38
|
+
- `warningLimit` the maximum number of joins allowed.
|
|
39
|
+
|
|
40
|
+
### Examples
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
- rule: tooManyUpdates
|
|
44
|
+
properties:
|
|
45
|
+
warningLimit: 20
|
|
46
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: unbatched-materialized-query
|
|
3
|
+
name: Unbatched materialized query
|
|
4
|
+
title: Unbatched materialized SQL query
|
|
5
|
+
references:
|
|
6
|
+
CWE-1049: https://cwe.mitre.org/data/definitions/1049.html
|
|
7
|
+
impactDomain: Performance
|
|
8
|
+
labels:
|
|
9
|
+
- dao.materialize
|
|
10
|
+
scope: command
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Finds large data sets that are queried from the database and loaded into memory.
|
|
14
|
+
|
|
15
|
+
### Rule logic
|
|
16
|
+
|
|
17
|
+
Examines all SQL SELECT queries (as opposed to insert/update). If the query satisfies any of the
|
|
18
|
+
following conditions:
|
|
19
|
+
|
|
20
|
+
- Has a LIMIT clause
|
|
21
|
+
- Has a COUNT clause at the top level
|
|
22
|
+
- Queries only for metadata (`sqlite_master` table)
|
|
23
|
+
|
|
24
|
+
then the query is skipped.
|
|
25
|
+
|
|
26
|
+
Otherwise, the rule checks to see if the query has an ancestor labeled `dao.materialize`. If so,
|
|
27
|
+
it's emitted as a finding.
|
|
28
|
+
|
|
29
|
+
### Notes
|
|
30
|
+
|
|
31
|
+
Materializing large amounts of data code objects is a frequent cause of poor performance and memory
|
|
32
|
+
exhaustion.
|
|
33
|
+
|
|
34
|
+
A `COUNT` or `LIMIT` clause is a good indication that the code is taking steps to limit the amount
|
|
35
|
+
of data that's loaded into memory.
|
|
36
|
+
|
|
37
|
+
### Resolution
|
|
38
|
+
|
|
39
|
+
If data is being loaded into memory from an un-LIMITed query:
|
|
40
|
+
|
|
41
|
+
- Consider whether the data processing that's being performed in-memory can be performed in the
|
|
42
|
+
database - either via SQL or a stored procedure.
|
|
43
|
+
- If the data is being loaded solely for presentation purposes, fetch data in batches - e.g. with a
|
|
44
|
+
pagination library.
|
|
45
|
+
|
|
46
|
+
### Options
|
|
47
|
+
|
|
48
|
+
None
|
|
49
|
+
|
|
50
|
+
### Examples
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
- rule: unbatchedMaterializedQuery
|
|
54
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: update-in-get-request
|
|
3
|
+
name: Update in get request
|
|
4
|
+
title: Data update performed in GET or HEAD request
|
|
5
|
+
impactDomain: Maintainability
|
|
6
|
+
labels:
|
|
7
|
+
- audit
|
|
8
|
+
scope: http_server_request
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Finds SQL updates that are performed in an HTTP server `GET` request.
|
|
12
|
+
|
|
13
|
+
### Rule logic
|
|
14
|
+
|
|
15
|
+
Checks each HTTP server `GET` and `HEAD` request. Within each of these requests, checks for SQL
|
|
16
|
+
queries that match the `queryInclude` option and don't match `queryExclude`. If any such queries
|
|
17
|
+
exist, they are emitted as findings.
|
|
18
|
+
|
|
19
|
+
### Notes
|
|
20
|
+
|
|
21
|
+
Performing data updates in a `GET` request is anti-pattern, and counter to the intent of HTTP. For
|
|
22
|
+
data modifications, use `PUT`, `POST`, or `PATCH`.
|
|
23
|
+
|
|
24
|
+
Data updates which are used for the purposes of tracking user activity are fine in any type of
|
|
25
|
+
request. Use the `queryExclude` option to allow these queries.
|
|
26
|
+
|
|
27
|
+
### Resolution
|
|
28
|
+
|
|
29
|
+
Perform data updates in `PUT`, `POST`, or `PATCH` requests.
|
|
30
|
+
|
|
31
|
+
### Options
|
|
32
|
+
|
|
33
|
+
- `queryInclude: RegExp[]`. Default: `[/\binsert\b/i, /\bupdate\b/i]`.
|
|
34
|
+
- `queryExclude: RegExp[]`. Default: empty.
|
|
35
|
+
|
|
36
|
+
### Examples
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- rule: updateInGetRequest
|
|
40
|
+
properties:
|
|
41
|
+
queryExclude:
|
|
42
|
+
- /\bINSERT\b/i
|
|
43
|
+
- /\bUPDATE\b/i
|
|
44
|
+
```
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appland/scanner",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": "built/cli.js",
|
|
6
6
|
"files": [
|
|
7
|
-
"built"
|
|
7
|
+
"built",
|
|
8
|
+
"doc"
|
|
8
9
|
],
|
|
9
10
|
"scripts": {
|
|
10
11
|
"build": "mkdir -p built && cp -r src/sampleConfig built && tsc && yarn schema && yarn doc",
|