@thymian/rules-rfc-6797 0.0.0-stage → 0.3.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.
- package/README.md +158 -2
- package/dist/coverage.d.ts +291 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +160 -0
- package/dist/coverage.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/effective-request-uri/hsts-host-must-not-treat-empty-path-as-slash-when-comparing-effective-request-uris.rule.d.ts +3 -0
- package/dist/rules/effective-request-uri/hsts-host-must-not-treat-empty-path-as-slash-when-comparing-effective-request-uris.rule.d.ts.map +1 -0
- package/dist/rules/effective-request-uri/hsts-host-must-not-treat-empty-path-as-slash-when-comparing-effective-request-uris.rule.js +12 -0
- package/dist/rules/effective-request-uri/hsts-host-must-not-treat-empty-path-as-slash-when-comparing-effective-request-uris.rule.js.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-must-not-send-sts-header-over-insecure-transport.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/hsts-host-must-not-send-sts-header-over-insecure-transport.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-must-not-send-sts-header-over-insecure-transport.rule.js +39 -0
- package/dist/rules/server-processing-model/hsts-host-must-not-send-sts-header-over-insecure-transport.rule.js.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-must-send-only-one-sts-header.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/hsts-host-must-send-only-one-sts-header.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-must-send-only-one-sts-header.rule.js +35 -0
- package/dist/rules/server-processing-model/hsts-host-must-send-only-one-sts-header.rule.js.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-should-redirect-insecure-requests-to-https.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/hsts-host-should-redirect-insecure-requests-to-https.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/hsts-host-should-redirect-insecure-requests-to-https.rule.js +24 -0
- package/dist/rules/server-processing-model/hsts-host-should-redirect-insecure-requests-to-https.rule.js.map +1 -0
- package/dist/rules/server-processing-model/https-redirect-is-should-for-deployment-reasons.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/https-redirect-is-should-for-deployment-reasons.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/https-redirect-is-should-for-deployment-reasons.rule.js +14 -0
- package/dist/rules/server-processing-model/https-redirect-is-should-for-deployment-reasons.rule.js.map +1 -0
- package/dist/rules/server-processing-model/server-may-establish-hsts-over-secure-transport.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/server-may-establish-hsts-over-secure-transport.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/server-may-establish-hsts-over-secure-transport.rule.js +19 -0
- package/dist/rules/server-processing-model/server-may-establish-hsts-over-secure-transport.rule.js.map +1 -0
- package/dist/rules/server-processing-model/server-should-redirect-insecure-requests-to-https.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/server-should-redirect-insecure-requests-to-https.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/server-should-redirect-insecure-requests-to-https.rule.js +25 -0
- package/dist/rules/server-processing-model/server-should-redirect-insecure-requests-to-https.rule.js.map +1 -0
- package/dist/rules/server-processing-model/server-should-send-sts-header-over-secure-transport.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/server-should-send-sts-header-over-secure-transport.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/server-should-send-sts-header-over-secure-transport.rule.js +22 -0
- package/dist/rules/server-processing-model/server-should-send-sts-header-over-secure-transport.rule.js.map +1 -0
- package/dist/rules/server-processing-model/sts-header-inclusion-is-should-to-accommodate-caches.rule.d.ts +3 -0
- package/dist/rules/server-processing-model/sts-header-inclusion-is-should-to-accommodate-caches.rule.d.ts.map +1 -0
- package/dist/rules/server-processing-model/sts-header-inclusion-is-should-to-accommodate-caches.rule.js +14 -0
- package/dist/rules/server-processing-model/sts-header-inclusion-is-should-to-accommodate-caches.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-may-assert-include-subdomains.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-may-assert-include-subdomains.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-may-assert-include-subdomains.rule.js +35 -0
- package/dist/rules/syntax/hsts-host-may-assert-include-subdomains.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-must-not-repeat-sts-directives.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-must-not-repeat-sts-directives.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-must-not-repeat-sts-directives.rule.js +33 -0
- package/dist/rules/syntax/hsts-host-must-not-repeat-sts-directives.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-include-subdomains-without-value.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-must-send-include-subdomains-without-value.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-include-subdomains-without-value.rule.js +24 -0
- package/dist/rules/syntax/hsts-host-must-send-include-subdomains-without-value.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-as-delta-seconds.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-as-delta-seconds.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-as-delta-seconds.rule.js +33 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-as-delta-seconds.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-directive.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-directive.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-directive.rule.js +24 -0
- package/dist/rules/syntax/hsts-host-must-send-max-age-directive.rule.js.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-sts-header-conforming-to-grammar.rule.d.ts +3 -0
- package/dist/rules/syntax/hsts-host-must-send-sts-header-conforming-to-grammar.rule.d.ts.map +1 -0
- package/dist/rules/syntax/hsts-host-must-send-sts-header-conforming-to-grammar.rule.js +29 -0
- package/dist/rules/syntax/hsts-host-must-send-sts-header-conforming-to-grammar.rule.js.map +1 -0
- package/dist/rules/syntax/user-agent-must-enforce-hsts-policy.rule.d.ts +3 -0
- package/dist/rules/syntax/user-agent-must-enforce-hsts-policy.rule.d.ts.map +1 -0
- package/dist/rules/syntax/user-agent-must-enforce-hsts-policy.rule.js +15 -0
- package/dist/rules/syntax/user-agent-must-enforce-hsts-policy.rule.js.map +1 -0
- package/dist/rules/syntax/user-agent-must-ignore-unrecognized-sts-directives.rule.d.ts +3 -0
- package/dist/rules/syntax/user-agent-must-ignore-unrecognized-sts-directives.rule.d.ts.map +1 -0
- package/dist/rules/syntax/user-agent-must-ignore-unrecognized-sts-directives.rule.js +37 -0
- package/dist/rules/syntax/user-agent-must-ignore-unrecognized-sts-directives.rule.js.map +1 -0
- package/dist/rules/utils/headers.d.ts +7 -0
- package/dist/rules/utils/headers.d.ts.map +1 -0
- package/dist/rules/utils/headers.js +54 -0
- package/dist/rules/utils/headers.js.map +1 -0
- package/dist/rules/utils/redirect.d.ts +8 -0
- package/dist/rules/utils/redirect.d.ts.map +1 -0
- package/dist/rules/utils/redirect.js +150 -0
- package/dist/rules/utils/redirect.js.map +1 -0
- package/dist/rules/utils/results.d.ts +5 -0
- package/dist/rules/utils/results.d.ts.map +1 -0
- package/dist/rules/utils/results.js +14 -0
- package/dist/rules/utils/results.js.map +1 -0
- package/dist/rules/utils/sts-contexts.d.ts +12 -0
- package/dist/rules/utils/sts-contexts.d.ts.map +1 -0
- package/dist/rules/utils/sts-contexts.js +69 -0
- package/dist/rules/utils/sts-contexts.js.map +1 -0
- package/dist/rules/utils/sts-field-value.d.ts +17 -0
- package/dist/rules/utils/sts-field-value.d.ts.map +1 -0
- package/dist/rules/utils/sts-field-value.js +133 -0
- package/dist/rules/utils/sts-field-value.js.map +1 -0
- package/dist/rules/utils/transport.d.ts +4 -0
- package/dist/rules/utils/transport.d.ts.map +1 -0
- package/dist/rules/utils/transport.js +24 -0
- package/dist/rules/utils/transport.js.map +1 -0
- package/package.json +55 -4
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RuleFnResult, RuleViolationLocation } from '@thymian/core';
|
|
2
|
+
export type RuleOptions = Record<PropertyKey, unknown>;
|
|
3
|
+
export declare function violation(location: RuleViolationLocation, message: string): RuleFnResult;
|
|
4
|
+
export declare function ruleSkip(location: RuleViolationLocation, ruleName: string, message: string): RuleFnResult;
|
|
5
|
+
//# sourceMappingURL=results.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../../src/rules/utils/results.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGzE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAEvD,wBAAgB,SAAS,CACvB,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,MAAM,GACd,YAAY,CAEd;AAID,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,YAAY,CAKd"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// What the rule functions of this package return — a violation, or a
|
|
2
|
+
// `rule-skip` for an input a rule cannot decide — and the options they take.
|
|
3
|
+
export function violation(location, message) {
|
|
4
|
+
return { location, violation: { message }, findings: [] };
|
|
5
|
+
}
|
|
6
|
+
// A result that says the rule could not decide this input, rather than pass
|
|
7
|
+
// it: a finding with no violation, which the reports render as skipped.
|
|
8
|
+
export function ruleSkip(location, ruleName, message) {
|
|
9
|
+
return {
|
|
10
|
+
location,
|
|
11
|
+
findings: [{ kind: 'rule-skip', title: ruleName, message }],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=results.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.js","sourceRoot":"","sources":["../../../src/rules/utils/results.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,6EAA6E;AAO7E,MAAM,UAAU,SAAS,CACvB,QAA+B,EAC/B,OAAe;IAEf,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,4EAA4E;AAC5E,wEAAwE;AACxE,MAAM,UAAU,QAAQ,CACtB,QAA+B,EAC/B,QAAgB,EAChB,OAAe;IAEf,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;KAC5D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ApiContext, type HttpResponse, type LintContext, type LiveApiContext, type RuleFn } from '@thymian/core';
|
|
2
|
+
import { type RuleOptions } from './results.js';
|
|
3
|
+
import { type StsDirective } from './sts-field-value.js';
|
|
4
|
+
export declare function liveStsValues(headers: HttpResponse['headers']): string[];
|
|
5
|
+
export type StsFieldCheck = (fieldValue: string) => string | undefined;
|
|
6
|
+
export declare function onConformingValue(check: (directives: StsDirective[], fieldValue: string) => string | undefined): StsFieldCheck;
|
|
7
|
+
export declare function stsValueRuleFns(ruleName: string, check: StsFieldCheck): {
|
|
8
|
+
lint: RuleFn<LintContext, RuleOptions>;
|
|
9
|
+
live: RuleFn<LiveApiContext, RuleOptions>;
|
|
10
|
+
};
|
|
11
|
+
export declare function stsPresenceRuleFn(message: string): RuleFn<ApiContext, RuleOptions>;
|
|
12
|
+
//# sourceMappingURL=sts-contexts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sts-contexts.d.ts","sourceRoot":"","sources":["../../../src/rules/utils/sts-contexts.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,UAAU,EAEf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EAGnB,KAAK,MAAM,EAGZ,MAAM,eAAe,CAAC;AAQvB,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,cAAc,CAAC;AACrE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAK9B,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,CAExE;AAGD,MAAM,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAKvE,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAC5E,aAAa,CAKf;AAKD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,GACnB;IACD,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;CAC3C,CAiDA;AAQD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAOjC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// The execution functions of the rules that check the Strict-Transport-
|
|
2
|
+
// Security header, and the STS field lines of a live response. The common
|
|
3
|
+
// interface is value-blind — it sees header names only — so every value
|
|
4
|
+
// check overrides all three contexts: `static` reads the value the API
|
|
5
|
+
// description pins, `test` and `analytics` read the value that was actually
|
|
6
|
+
// sent. Presence, a name, is the one check the common interface carries.
|
|
7
|
+
import { constant, protocol, responseHeader, } from '@thymian/core';
|
|
8
|
+
import { carriesHeader, describedTransaction, liveHeaderValues, pinnedHeaderValues, } from './headers.js';
|
|
9
|
+
import { ruleSkip, violation } from './results.js';
|
|
10
|
+
import { parseStsFieldValue, STS_HEADER, } from './sts-field-value.js';
|
|
11
|
+
// Every STS field line of a live response. More than one is what
|
|
12
|
+
// `hsts-host-must-send-only-one-sts-header` checks; a value rule holds each
|
|
13
|
+
// field line to its requirement on its own.
|
|
14
|
+
export function liveStsValues(headers) {
|
|
15
|
+
return liveHeaderValues(headers, STS_HEADER);
|
|
16
|
+
}
|
|
17
|
+
// A directive-level rule owns one requirement and takes the generic grammar
|
|
18
|
+
// for granted: a field value that does not parse is left to the grammar rule,
|
|
19
|
+
// which reports it once — one defect, one violation — and passes here.
|
|
20
|
+
export function onConformingValue(check) {
|
|
21
|
+
return (fieldValue) => {
|
|
22
|
+
const parsed = parseStsFieldValue(fieldValue);
|
|
23
|
+
return parsed.conforms ? check(parsed.directives, fieldValue) : undefined;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// The execution functions of a rule that holds every STS field value to one
|
|
27
|
+
// check: `lint` for `.overrideStaticRule()`, `live` for `.overrideTest()` and
|
|
28
|
+
// `.overrideAnalyticsRule()`.
|
|
29
|
+
export function stsValueRuleFns(ruleName, check) {
|
|
30
|
+
const evaluate = (location, fieldValues) => {
|
|
31
|
+
const problems = fieldValues
|
|
32
|
+
.map(check)
|
|
33
|
+
.filter((problem) => problem !== undefined);
|
|
34
|
+
return problems.length === 0
|
|
35
|
+
? []
|
|
36
|
+
: [violation(location, problems.join(' '))];
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
// A function validator, not the lint context's `validateHttpTransactions`:
|
|
40
|
+
// that one keeps only results carrying a violation, and an unpinned value
|
|
41
|
+
// must surface as a `rule-skip` rather than vanish into a pass.
|
|
42
|
+
lint: (ctx) => ctx.validateCommonHttpTransactions(responseHeader(STS_HEADER), (_req, _res, location) => {
|
|
43
|
+
const res = describedTransaction(ctx, location)?.thymianRes;
|
|
44
|
+
const values = res === undefined ? undefined : pinnedHeaderValues(res, STS_HEADER);
|
|
45
|
+
if (values === undefined) {
|
|
46
|
+
return [
|
|
47
|
+
ruleSkip(location, ruleName, 'The API description declares Strict-Transport-Security without pinning its value (const, enum or examples), so the value cannot be checked statically.'),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
return evaluate(location, values);
|
|
51
|
+
}),
|
|
52
|
+
// `constant(true)` as the candidate filter: `test` picks the requests it
|
|
53
|
+
// sends by the candidate filter alone, over the *described* transactions,
|
|
54
|
+
// so a response-side candidate (`responseHeader(STS_HEADER)`) would only
|
|
55
|
+
// send the requests whose description already declares the header — and
|
|
56
|
+
// miss a server that sends it where the description does not say so.
|
|
57
|
+
live: (ctx) => ctx.validateHttpTransactions(constant(true), (_req, res, location) => evaluate(location, liveStsValues(res.headers))),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// The execution function of a rule that flags a response over secure
|
|
61
|
+
// transport without a Strict-Transport-Security header. Presence is the one
|
|
62
|
+
// STS check the common interface can carry on its own: it sees the scheme
|
|
63
|
+
// through its request filter and header names on the response, so one
|
|
64
|
+
// function serves all three contexts — the declared headers in `static`, the
|
|
65
|
+
// headers sent in `test` and `analytics`.
|
|
66
|
+
export function stsPresenceRuleFn(message) {
|
|
67
|
+
return (ctx) => ctx.validateCommonHttpTransactions(protocol('https'), (_req, res, location) => carriesHeader(res, STS_HEADER) ? [] : [violation(location, message)]);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=sts-contexts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sts-contexts.js","sourceRoot":"","sources":["../../../src/rules/utils/sts-contexts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const STS_HEADER = "strict-transport-security";
|
|
2
|
+
export type StsDirective = {
|
|
3
|
+
name: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
};
|
|
6
|
+
export type StsFieldValue = {
|
|
7
|
+
conforms: true;
|
|
8
|
+
directives: StsDirective[];
|
|
9
|
+
} | {
|
|
10
|
+
conforms: false;
|
|
11
|
+
problem: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function parseStsFieldValue(fieldValue: string): StsFieldValue;
|
|
14
|
+
export declare function findDirectives(directives: readonly StsDirective[], name: string): StsDirective[];
|
|
15
|
+
export declare function isDeltaSeconds(value: string | undefined): value is string;
|
|
16
|
+
export declare function maxAgeSeconds(directives: readonly StsDirective[]): number | undefined;
|
|
17
|
+
//# sourceMappingURL=sts-field-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sts-field-value.d.ts","sourceRoot":"","sources":["../../../src/rules/utils/sts-field-value.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,UAAU,8BAA8B,CAAC;AAMtD,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,YAAY,EAAE,CAAA;CAAE,GAC9C;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAqBzC,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAqGpE;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,SAAS,YAAY,EAAE,EACnC,IAAI,EAAE,MAAM,GACX,YAAY,EAAE,CAEhB;AAGD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAEzE;AAKD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,SAAS,YAAY,EAAE,GAClC,MAAM,GAAG,SAAS,CAGpB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// The Strict-Transport-Security field value, parsed against RFC 6797 §6.1:
|
|
2
|
+
//
|
|
3
|
+
// Strict-Transport-Security = "Strict-Transport-Security" ":"
|
|
4
|
+
// [ directive ] *( ";" [ directive ] )
|
|
5
|
+
// directive = directive-name [ "=" directive-value ]
|
|
6
|
+
// directive-name = token
|
|
7
|
+
// directive-value = token | quoted-string
|
|
8
|
+
//
|
|
9
|
+
// with RFC 2616's token and quoted-string, and its implied linear whitespace
|
|
10
|
+
// between them. This is the generic grammar only: what each directive must
|
|
11
|
+
// look like (max-age's delta-seconds, includeSubDomains being valueless, no
|
|
12
|
+
// directive twice) is left to the rule that owns that requirement, so one
|
|
13
|
+
// defect in a header yields one violation from one rule.
|
|
14
|
+
export const STS_HEADER = 'strict-transport-security';
|
|
15
|
+
// RFC 2616 §2.2: token = 1*<any CHAR except CTLs or separators>.
|
|
16
|
+
const SEPARATORS = new Set('()<>@,;:\\"/[]?={} \t');
|
|
17
|
+
function isTokenChar(char) {
|
|
18
|
+
const code = char.charCodeAt(0);
|
|
19
|
+
return code > 31 && code < 127 && !SEPARATORS.has(char);
|
|
20
|
+
}
|
|
21
|
+
// RFC 2616 §2.2: qdtext is any TEXT but <">, and TEXT is any octet except
|
|
22
|
+
// CTLs but including linear whitespace, so a horizontal tab stays.
|
|
23
|
+
function isControl(char) {
|
|
24
|
+
const code = char.charCodeAt(0);
|
|
25
|
+
return (code < 32 && char !== '\t') || code === 127;
|
|
26
|
+
}
|
|
27
|
+
function describeChar(char) {
|
|
28
|
+
return char === undefined ? 'the end of the value' : JSON.stringify(char);
|
|
29
|
+
}
|
|
30
|
+
export function parseStsFieldValue(fieldValue) {
|
|
31
|
+
const directives = [];
|
|
32
|
+
let i = 0;
|
|
33
|
+
const skipWhitespace = () => {
|
|
34
|
+
while (fieldValue[i] === ' ' || fieldValue[i] === '\t') {
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const readToken = () => {
|
|
39
|
+
const start = i;
|
|
40
|
+
while (i < fieldValue.length && isTokenChar(fieldValue[i])) {
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
return fieldValue.slice(start, i);
|
|
44
|
+
};
|
|
45
|
+
// Positioned on the opening quote; returns the unescaped content, or
|
|
46
|
+
// undefined when the string never closes or carries a control character.
|
|
47
|
+
// A quoted-pair is "\" CHAR, so only US-ASCII may be escaped.
|
|
48
|
+
const readQuotedString = () => {
|
|
49
|
+
let content = '';
|
|
50
|
+
i++;
|
|
51
|
+
while (i < fieldValue.length) {
|
|
52
|
+
const char = fieldValue[i];
|
|
53
|
+
if (char === '"') {
|
|
54
|
+
i++;
|
|
55
|
+
return content;
|
|
56
|
+
}
|
|
57
|
+
if (char === '\\') {
|
|
58
|
+
const escaped = fieldValue[i + 1];
|
|
59
|
+
if (escaped === undefined || escaped.charCodeAt(0) > 127) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
content += escaped;
|
|
63
|
+
i += 2;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (isControl(char)) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
content += char;
|
|
70
|
+
i++;
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
};
|
|
74
|
+
const fail = (problem) => ({
|
|
75
|
+
conforms: false,
|
|
76
|
+
problem,
|
|
77
|
+
});
|
|
78
|
+
for (;;) {
|
|
79
|
+
skipWhitespace();
|
|
80
|
+
// An empty directive — nothing before the next ";" or the end — is
|
|
81
|
+
// allowed by `[ directive ] *( ";" [ directive ] )`.
|
|
82
|
+
if (i < fieldValue.length && fieldValue[i] !== ';') {
|
|
83
|
+
const name = readToken();
|
|
84
|
+
if (name === '') {
|
|
85
|
+
return fail(`expected a directive name but found ${describeChar(fieldValue[i])}`);
|
|
86
|
+
}
|
|
87
|
+
skipWhitespace();
|
|
88
|
+
let value;
|
|
89
|
+
if (fieldValue[i] === '=') {
|
|
90
|
+
i++;
|
|
91
|
+
skipWhitespace();
|
|
92
|
+
if (fieldValue[i] === '"') {
|
|
93
|
+
value = readQuotedString();
|
|
94
|
+
if (value === undefined) {
|
|
95
|
+
return fail(`the quoted value of "${name}" is malformed`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
value = readToken();
|
|
100
|
+
if (value === '') {
|
|
101
|
+
return fail(`"${name}=" is followed by ${describeChar(fieldValue[i])} instead of a token or a quoted-string`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
skipWhitespace();
|
|
105
|
+
}
|
|
106
|
+
directives.push(value === undefined
|
|
107
|
+
? { name: name.toLowerCase() }
|
|
108
|
+
: { name: name.toLowerCase(), value });
|
|
109
|
+
}
|
|
110
|
+
if (i >= fieldValue.length) {
|
|
111
|
+
return { conforms: true, directives };
|
|
112
|
+
}
|
|
113
|
+
if (fieldValue[i] !== ';') {
|
|
114
|
+
return fail(`directives must be separated by ";", but ${describeChar(fieldValue[i])} follows "${fieldValue.slice(0, i).trim()}"`);
|
|
115
|
+
}
|
|
116
|
+
i++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function findDirectives(directives, name) {
|
|
120
|
+
return directives.filter((directive) => directive.name === name);
|
|
121
|
+
}
|
|
122
|
+
// RFC 2616 §3.3.2: delta-seconds = 1*DIGIT.
|
|
123
|
+
export function isDeltaSeconds(value) {
|
|
124
|
+
return value !== undefined && /^[0-9]+$/.test(value);
|
|
125
|
+
}
|
|
126
|
+
// The policy's lifetime: the first max-age, in seconds. `undefined` when
|
|
127
|
+
// there is none or its value is not delta-seconds — each another rule's
|
|
128
|
+
// defect, and in either case no policy is in effect to judge.
|
|
129
|
+
export function maxAgeSeconds(directives) {
|
|
130
|
+
const value = findDirectives(directives, 'max-age')[0]?.value;
|
|
131
|
+
return isDeltaSeconds(value) ? Number(value) : undefined;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=sts-field-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sts-field-value.js","sourceRoot":"","sources":["../../../src/rules/utils/sts-field-value.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RuleFnResult, RuleViolationLocation } from '@thymian/core';
|
|
2
|
+
export declare function isServerFallbackOrigin(origin: string): boolean;
|
|
3
|
+
export declare function serverFallbackSkip(location: RuleViolationLocation, ruleName: string): RuleFnResult;
|
|
4
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/rules/utils/transport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAezE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAM9D;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,MAAM,GACf,YAAY,CAMd"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// The transport a request travelled over, as far as a rule may judge it.
|
|
2
|
+
import { ruleSkip } from './results.js';
|
|
3
|
+
// A document with no `servers` entry, a relative server URL, or a variable
|
|
4
|
+
// in the scheme or port that cannot be resolved is loaded as
|
|
5
|
+
// `http://localhost:8080`: the scheme is Thymian's fallback, not the API's.
|
|
6
|
+
// A rule judging the scheme skips exactly that origin in `static` and in
|
|
7
|
+
// `test`, whose requests carry the described origin even when sent to a
|
|
8
|
+
// target URL, rather than report a transport the description never declared.
|
|
9
|
+
// A description that really declares `http://localhost:8080` is a local
|
|
10
|
+
// development server, where HSTS is not demanded in practice either.
|
|
11
|
+
// `analytics` never skips it: recorded traffic is real.
|
|
12
|
+
const SERVER_FALLBACK_ORIGIN = 'http://localhost:8080';
|
|
13
|
+
export function isServerFallbackOrigin(origin) {
|
|
14
|
+
try {
|
|
15
|
+
return new URL(origin).origin === SERVER_FALLBACK_ORIGIN;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function serverFallbackSkip(location, ruleName) {
|
|
22
|
+
return ruleSkip(location, ruleName, `This request is served from ${SERVER_FALLBACK_ORIGIN}, which is also what Thymian loads an API description without a usable server URL as, so its scheme may be Thymian's rather than the API's and the transport is not judged.`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/rules/utils/transport.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAIzE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,2EAA2E;AAC3E,6DAA6D;AAC7D,4EAA4E;AAC5E,yEAAyE;AACzE,wEAAwE;AACxE,6EAA6E;AAC7E,wEAAwE;AACxE,qEAAqE;AACrE,wDAAwD;AACxD,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAEvD,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,sBAAsB,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,QAA+B,EAC/B,QAAgB;IAEhB,OAAO,QAAQ,CACb,QAAQ,EACR,QAAQ,EACR,+BAA+B,sBAAsB,6KAA6K,CACnO,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thymian/rules-rfc-6797",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Thymian rule set implementing RFC 6797 HTTP Strict Transport Security (HSTS) validation",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/thymianofficial/thymian/issues"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://thymian.dev",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/thymianofficial/thymian.git",
|
|
13
|
+
"directory": "packages/rules-rfc-6797"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"thymian",
|
|
23
|
+
"api-governance",
|
|
24
|
+
"http",
|
|
25
|
+
"http-conformance",
|
|
26
|
+
"http-rules",
|
|
27
|
+
"hsts",
|
|
28
|
+
"strict-transport-security",
|
|
29
|
+
"rfc-6797"
|
|
30
|
+
],
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"module": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"type": "module",
|
|
35
|
+
"exports": {
|
|
36
|
+
"./package.json": "./package.json",
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"import": "./dist/index.js",
|
|
40
|
+
"default": "./dist/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"!**/*.tsbuildinfo"
|
|
46
|
+
],
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@thymian/core": "0.3.0",
|
|
49
|
+
"tslib": "^2.3.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@thymian/core-testing": "0.3.0",
|
|
53
|
+
"@thymian/plugin-http-analyzer": "0.3.0",
|
|
54
|
+
"@thymian/plugin-http-linter": "0.3.0",
|
|
55
|
+
"@thymian/plugin-http-tester": "0.3.0"
|
|
56
|
+
}
|
|
57
|
+
}
|