host-consensus 0.1.0 → 0.1.2
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 +17 -17
- package/VERIFY.md +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.npmjs.com/package/host-consensus)
|
|
9
9
|
|
|
10
|
-
A runtime-path library
|
|
10
|
+
A runtime-path library: you import it into request-validation code and ship it.
|
|
11
11
|
Zero runtime dependencies. TypeScript, ES2022, dual ESM/CJS, with a small CLI.
|
|
12
12
|
|
|
13
13
|
```bash
|
|
@@ -16,8 +16,8 @@ npm install host-consensus
|
|
|
16
16
|
|
|
17
17
|
| | reads the host as |
|
|
18
18
|
|---|---|
|
|
19
|
-
| `new URL()
|
|
20
|
-
| `urllib.parse
|
|
19
|
+
| `new URL()`, the WHATWG rules every browser and Node run | **example.com** |
|
|
20
|
+
| `urllib.parse`, the RFC 3986 rules most of the non-browser world runs | **evil.com** |
|
|
21
21
|
|
|
22
22
|
Validate that URL in Node against an allowlist and it passes as `example.com`.
|
|
23
23
|
Hand the same *string* to a Python service, a Go proxy, or anything else built
|
|
@@ -74,10 +74,10 @@ $ echo $?
|
|
|
74
74
|
|
|
75
75
|
## The seven constructions
|
|
76
76
|
|
|
77
|
-
Over a deterministic enumeration of 312 URLs
|
|
78
|
-
constructions x 6 path suffixes
|
|
77
|
+
Over a deterministic enumeration of 312 URLs (2 schemes x 26 authority
|
|
78
|
+
constructions x 6 path suffixes), **84 rows** are read as a different host by
|
|
79
79
|
the two conventions. Seven distinct authority constructions sit behind them, and
|
|
80
|
-
each
|
|
80
|
+
each one works differently:
|
|
81
81
|
|
|
82
82
|
| authority | WHATWG reads | RFC 3986 reads | why |
|
|
83
83
|
|---|---|---|---|
|
|
@@ -94,19 +94,19 @@ The IPv4 rows run the other way from the backslash row: `http://2130706433` is
|
|
|
94
94
|
hostname to anything RFC-derived. Whichever side does the blocking, the other
|
|
95
95
|
side disagrees about what it is blocking.
|
|
96
96
|
|
|
97
|
-
A further **48 rows** across four constructions are an *acceptance* difference
|
|
98
|
-
one convention refuses the URL outright and the other returns a host:
|
|
97
|
+
A further **48 rows** across four constructions are an *acceptance* difference,
|
|
98
|
+
where one convention refuses the URL outright and the other returns a host:
|
|
99
99
|
`exa mple.com`, `example.com:65536`, `example.com:+80`, `example.com: 80`.
|
|
100
100
|
|
|
101
101
|
The remaining **180 rows** are reported as agreeing. That matters as much as the
|
|
102
|
-
rest: differences in spelling
|
|
102
|
+
rest: differences in spelling, such as IPv6 brackets and host case, are normalised away
|
|
103
103
|
and never reported, so ordinary URLs come back clean.
|
|
104
104
|
|
|
105
105
|
## What this does not do
|
|
106
106
|
|
|
107
107
|
It does not resolve DNS, classify addresses as private, or make requests. Those
|
|
108
108
|
are a different job, and [`request-filtering-agent`](https://www.npmjs.com/package/request-filtering-agent)
|
|
109
|
-
does them well
|
|
109
|
+
does them well, blocking requests to private ranges at the agent level. Use it
|
|
110
110
|
for that; use this to check that the URL string you validated is the one your
|
|
111
111
|
next hop will read.
|
|
112
112
|
|
|
@@ -125,9 +125,9 @@ class HostDisagreementError extends Error { readonly consensus: Consensus }
|
|
|
125
125
|
|
|
126
126
|
`verdict` is one of:
|
|
127
127
|
|
|
128
|
-
- `'agreed'
|
|
129
|
-
- `'host-differs'
|
|
130
|
-
- `'acceptance-differs'
|
|
128
|
+
- `'agreed'`: every convention names the same host.
|
|
129
|
+
- `'host-differs'`: all parsed, and they name different hosts.
|
|
130
|
+
- `'acceptance-differs'`: at least one refused and at least one accepted.
|
|
131
131
|
|
|
132
132
|
`inspect` throws `TypeError` on a non-string and nothing else. `agrees` never
|
|
133
133
|
throws on a malformed URL: a predicate that throws gets read as `false` by the
|
|
@@ -135,8 +135,8 @@ next person to use it, and "this URL is dangerous" must not be reachable by
|
|
|
135
135
|
accident. `assertConsensus` also throws when both conventions refuse, because
|
|
136
136
|
there is no host to return.
|
|
137
137
|
|
|
138
|
-
`inspect` performs no I/O
|
|
139
|
-
function of its argument.
|
|
138
|
+
`inspect` performs no I/O at all (no network, no filesystem, no clock) and is a
|
|
139
|
+
pure function of its argument.
|
|
140
140
|
|
|
141
141
|
## How the RFC 3986 reading is checked
|
|
142
142
|
|
|
@@ -150,8 +150,8 @@ headline claim from a clean install in under a minute.
|
|
|
150
150
|
|
|
151
151
|
[`yaml-drift`](https://www.npmjs.com/package/yaml-drift) reports every value
|
|
152
152
|
whose meaning changed converting YAML to JSON; `host-consensus` reports hosts
|
|
153
|
-
that two URL conventions read differently. Same shape
|
|
154
|
-
changes meaning
|
|
153
|
+
that two URL conventions read differently. Same shape, a boundary that quietly
|
|
154
|
+
changes meaning, in a different place.
|
|
155
155
|
|
|
156
156
|
## License
|
|
157
157
|
|
package/VERIFY.md
CHANGED
|
@@ -5,7 +5,7 @@ different hosts depending on which convention reads it, and that
|
|
|
5
5
|
`host-consensus` catches that.
|
|
6
6
|
|
|
7
7
|
Reproduce it from a clean directory. Nothing here needs a checkout of this
|
|
8
|
-
repository
|
|
8
|
+
repository, since it installs the published package from the registry.
|
|
9
9
|
|
|
10
10
|
## 1. Install
|
|
11
11
|
|
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ interface Reading {
|
|
|
6
6
|
host: string | null;
|
|
7
7
|
/**
|
|
8
8
|
* The port as a string; `''` when the URL carries no port. `null` when this
|
|
9
|
-
* convention produced no usable port
|
|
9
|
+
* convention produced no usable port, either because it refused the URL, or
|
|
10
10
|
* because the port is present but not an integer in 0-65535.
|
|
11
11
|
*/
|
|
12
12
|
port: string | null;
|
|
@@ -35,7 +35,7 @@ interface Consensus {
|
|
|
35
35
|
* and ASCII case is folded; nothing else. A difference that survives this is a
|
|
36
36
|
* disagreement about which host is named. A difference that does not survive it
|
|
37
37
|
* is a difference in spelling, and reporting those would make the tool
|
|
38
|
-
* unusable
|
|
38
|
+
* unusable, because it would flag every IPv6 URL in the world.
|
|
39
39
|
*/
|
|
40
40
|
declare function normaliseHost(host: string): string;
|
|
41
41
|
|
|
@@ -48,7 +48,7 @@ declare function inspect(url: string): Consensus;
|
|
|
48
48
|
/**
|
|
49
49
|
* `true` when every convention names the same host.
|
|
50
50
|
*
|
|
51
|
-
* Never throws on a malformed URL
|
|
51
|
+
* Never throws on a malformed URL. A predicate that throws gets read as
|
|
52
52
|
* `false` by the next person to use it, and "this URL is dangerous" must not
|
|
53
53
|
* be reachable by accident.
|
|
54
54
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ interface Reading {
|
|
|
6
6
|
host: string | null;
|
|
7
7
|
/**
|
|
8
8
|
* The port as a string; `''` when the URL carries no port. `null` when this
|
|
9
|
-
* convention produced no usable port
|
|
9
|
+
* convention produced no usable port, either because it refused the URL, or
|
|
10
10
|
* because the port is present but not an integer in 0-65535.
|
|
11
11
|
*/
|
|
12
12
|
port: string | null;
|
|
@@ -35,7 +35,7 @@ interface Consensus {
|
|
|
35
35
|
* and ASCII case is folded; nothing else. A difference that survives this is a
|
|
36
36
|
* disagreement about which host is named. A difference that does not survive it
|
|
37
37
|
* is a difference in spelling, and reporting those would make the tool
|
|
38
|
-
* unusable
|
|
38
|
+
* unusable, because it would flag every IPv6 URL in the world.
|
|
39
39
|
*/
|
|
40
40
|
declare function normaliseHost(host: string): string;
|
|
41
41
|
|
|
@@ -48,7 +48,7 @@ declare function inspect(url: string): Consensus;
|
|
|
48
48
|
/**
|
|
49
49
|
* `true` when every convention names the same host.
|
|
50
50
|
*
|
|
51
|
-
* Never throws on a malformed URL
|
|
51
|
+
* Never throws on a malformed URL. A predicate that throws gets read as
|
|
52
52
|
* `false` by the next person to use it, and "this URL is dangerous" must not
|
|
53
53
|
* be reachable by accident.
|
|
54
54
|
*/
|