@produtype/core 1.15.0 → 1.17.0
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.
|
@@ -10,7 +10,21 @@ const valuesFromPackage_1 = require("./structural/valuesFromPackage");
|
|
|
10
10
|
const readingDepth_1 = require("./readingDepth");
|
|
11
11
|
const developmentOnly_1 = require("./developmentOnly");
|
|
12
12
|
/** Lines that decide which origins may call this server. */
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The header, spelled the way each language spells it.
|
|
15
|
+
*
|
|
16
|
+
* photoprism refers to its headers by the constants it declared for them —
|
|
17
|
+
* `c.Header(header.AccessControlAllowOrigin, header.Any)` in `start.go` and
|
|
18
|
+
* `static.go`, which is where it opens itself — and those lines carry no hyphens, so
|
|
19
|
+
* a pattern written as the wire name could not see any of them. Excluding the
|
|
20
|
+
* constant table without this took the project from a right verdict on the wrong
|
|
21
|
+
* evidence to no verdict at all, which is worse.
|
|
22
|
+
*
|
|
23
|
+
* The camel spelling is still the protocol's name: Go, Java and C# write
|
|
24
|
+
* `AccessControlAllowOrigin` because that is what their conventions do to
|
|
25
|
+
* `Access-Control-Allow-Origin`. It is not the author's word either way.
|
|
26
|
+
*/
|
|
27
|
+
const ORIGIN_HANDLING = [/Access-Control-Allow-Origin/i, /\bAccessControlAllowOrigin\b/, /ALLOWED_ORIGINS/, /allowedOrigins/i];
|
|
14
28
|
/** A header name used as a key into a headers object: a lookup, not a decision. */
|
|
15
29
|
const READS_A_HEADER = /\[\s*(['"`])[^'"`]+\1\s*\](?!\s*=[^=])/;
|
|
16
30
|
/** The calls that put one on a response, in the frameworks this reads. */
|
|
@@ -726,6 +740,36 @@ async function detectSecurity(ctx) {
|
|
|
726
740
|
* `CORS_ORIGIN_ALLOW_ALL`, which is what it was called before version 3.5 — is the
|
|
727
741
|
* one line that opens it.
|
|
728
742
|
*/
|
|
743
|
+
/**
|
|
744
|
+
* Rust's answer, which is a builder rather than a value.
|
|
745
|
+
*
|
|
746
|
+
* meilisearch calls `.send_wildcard()` and `.allow_any_origin()` on an
|
|
747
|
+
* `actix_cors::Cors` — the most explicit way there is to say "everybody" — and the
|
|
748
|
+
* report said "CORS configuration not detected". Third product in three releases
|
|
749
|
+
* scoring well while answering every origin on the web, after kimai's
|
|
750
|
+
* `nelmio_cors.yaml` and chatwoot's `origins '*'`.
|
|
751
|
+
*
|
|
752
|
+
* Nothing here is a header name or an `allowedOrigins` field. `Cors`,
|
|
753
|
+
* `allow_any_origin`, `allowed_origin` and `permissive` are actix-cors'; `CorsLayer`
|
|
754
|
+
* and `allow_origin` are tower-http's. The method says which branch it is:
|
|
755
|
+
* `allow_any_origin`, `permissive` and `Any` are open, a named origin is a choice.
|
|
756
|
+
*
|
|
757
|
+
* The tower-http half ships weaker and this says so: meilisearch is the actix case,
|
|
758
|
+
* and two axum services cloned looking for the other one — atuin and lapdev — turned
|
|
759
|
+
* out to configure no CORS at all. It is the same contract read from the same kind
|
|
760
|
+
* of builder, but no repository stands behind it yet.
|
|
761
|
+
*/
|
|
762
|
+
const RUST_CORS_OPEN = [/\.allow_any_origin\s*\(/, /\.send_wildcard\s*\(/, /Cors::permissive\s*\(/, /CorsLayer::permissive\s*\(/, /\.allow_origin\s*\(\s*Any\b/];
|
|
763
|
+
const RUST_CORS_CHOSEN = [/\.allowed_origin\s*\(/, /\.allowed_origin_fn\s*\(/, /\.allow_origin\s*\(\s*["'[]/];
|
|
764
|
+
const rustSource = source.filter((f) => /\.rs$/.test(f));
|
|
765
|
+
if (rustSource.length > 0) {
|
|
766
|
+
const open = await (0, textSearch_1.searchInFiles)(ctx.root, rustSource, RUST_CORS_OPEN, 5);
|
|
767
|
+
const chosen = await (0, textSearch_1.searchInFiles)(ctx.root, rustSource, RUST_CORS_CHOSEN, 5);
|
|
768
|
+
for (const hit of open)
|
|
769
|
+
corsLoose.push(hit);
|
|
770
|
+
for (const hit of chosen)
|
|
771
|
+
corsStrict.push(hit);
|
|
772
|
+
}
|
|
729
773
|
/**
|
|
730
774
|
* Rails' answer, which is a gem with a small language of its own.
|
|
731
775
|
*
|
package/dist/utils/textSearch.js
CHANGED
|
@@ -26,6 +26,33 @@ const blockComments_1 = require("../analyzer/blockComments");
|
|
|
26
26
|
* and is left alone.
|
|
27
27
|
*/
|
|
28
28
|
const PATTERN_DECLARATION = /^(?:const\s+\w+(?:\s*:[^=]+)?\s*=\s*)?\/(?:[^/\\]|\\.)+\/[gimsuy]*\s*[,;]?$/;
|
|
29
|
+
/**
|
|
30
|
+
* A constant that spells its own name.
|
|
31
|
+
*
|
|
32
|
+
* photoprism keeps `AccessControlAllowOrigin = "Access-Control-Allow-Origin"` in
|
|
33
|
+
* `pkg/http/header/cors.go`, beside three more of the same, and that table was the
|
|
34
|
+
* whole evidence for its cross-origin finding — while
|
|
35
|
+
* `c.Header(header.AccessControlAllowOrigin, header.Any)` in `start.go` and
|
|
36
|
+
* `static.go`, the lines that actually open it, went uncited.
|
|
37
|
+
*
|
|
38
|
+
* A line whose value is its own identifier written out is a name for something, not a
|
|
39
|
+
* use of it. It is the third member of a family this file already has: a regex in a
|
|
40
|
+
* table is not a search, a name given a type is not a decision, and a header constant
|
|
41
|
+
* is not a header.
|
|
42
|
+
*
|
|
43
|
+
* Compared after normalising case and separators, because that is the only difference
|
|
44
|
+
* between the two halves — `ACCESS_CONTROL_ALLOW_ORIGIN`, `AccessControlAllowOrigin`
|
|
45
|
+
* and `"access-control-allow-origin"` are one string spelled three ways. A trailing
|
|
46
|
+
* comment is dropped first; Go puts the documentation link on the same line.
|
|
47
|
+
*/
|
|
48
|
+
function spellsItsOwnName(trimmed) {
|
|
49
|
+
const withoutComment = trimmed.replace(/\s*(\/\/|#).*$/, '').replace(/[,;]\s*$/, '');
|
|
50
|
+
const assignment = /^(?:const|let|var|final|static|public|private)?\s*([A-Za-z_][\w.]*)\s*(?::\s*[\w<>[\].]+)?\s*=\s*(['"`])([^'"`]+)\2$/.exec(withoutComment);
|
|
51
|
+
if (!assignment)
|
|
52
|
+
return false;
|
|
53
|
+
const plain = (value) => value.toLowerCase().replace(/[-_.\s]/g, '');
|
|
54
|
+
return plain(assignment[1]) === plain(assignment[3]);
|
|
55
|
+
}
|
|
29
56
|
/**
|
|
30
57
|
* A name given a type, rather than a value.
|
|
31
58
|
*
|
|
@@ -92,7 +119,7 @@ function declaresAType(trimmed) {
|
|
|
92
119
|
}
|
|
93
120
|
function declaresRatherThanDoes(line) {
|
|
94
121
|
const trimmed = line.trim();
|
|
95
|
-
return COMMENT_LINE.test(trimmed) || PATTERN_DECLARATION.test(trimmed) || declaresAType(trimmed);
|
|
122
|
+
return COMMENT_LINE.test(trimmed) || PATTERN_DECLARATION.test(trimmed) || declaresAType(trimmed) || spellsItsOwnName(trimmed);
|
|
96
123
|
}
|
|
97
124
|
/**
|
|
98
125
|
* Whether this line may be quoted back to the reader as something the code does.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@produtype/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "Deterministic CLI and library that analyzes a web application repository and reports how far it is from production-ready for the kind of product it is meant to be.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|