header-grader 0.1.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.
@@ -0,0 +1,64 @@
1
+ import { H as Headers, R as Report, a as Rule, S as ScanContext, C as CheckResult, G as Grade } from './middleware-BsJGVvzp.js';
2
+ export { M as MiddlewareOptions, b as Status, h as headerGrader } from './middleware-BsJGVvzp.js';
3
+ import 'node:http';
4
+
5
+ declare function isLocalHttpUrl(url: URL): boolean;
6
+ /** Grade a set of already-collected headers (used by the middleware and tests). */
7
+ declare function gradeHeaders(headers: Headers, opts?: {
8
+ url?: string;
9
+ isLocalHttp?: boolean;
10
+ }): Report;
11
+ /** Fetch a URL and grade its response headers. */
12
+ declare function scan(rawUrl: string, opts?: {
13
+ timeoutMs?: number;
14
+ }): Promise<Report>;
15
+
16
+ /**
17
+ * Recommended values used both for grading hints and for the config
18
+ * generators, so the report and the generated snippets always agree.
19
+ */
20
+ declare const RECOMMENDED: {
21
+ readonly "Content-Security-Policy": "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'";
22
+ readonly "Strict-Transport-Security": "max-age=31536000; includeSubDomains";
23
+ readonly "X-Content-Type-Options": "nosniff";
24
+ readonly "X-Frame-Options": "SAMEORIGIN";
25
+ readonly "Referrer-Policy": "strict-origin-when-cross-origin";
26
+ readonly "Permissions-Policy": "camera=(), microphone=(), geolocation=()";
27
+ readonly "Cross-Origin-Opener-Policy": "same-origin";
28
+ readonly "Cross-Origin-Resource-Policy": "same-origin";
29
+ };
30
+ /**
31
+ * Concrete attack scenarios, keyed by header. Attached to any check that
32
+ * doesn't pass, so the report can teach *why* the header matters, not just
33
+ * that it's missing. Shown by `--explain` and always present in JSON output.
34
+ */
35
+ declare const EXPLOITS: Record<string, string>;
36
+ declare const rules: Rule[];
37
+ declare function runRules(ctx: ScanContext): CheckResult[];
38
+
39
+ declare function scoreOf(results: CheckResult[]): number;
40
+ declare function gradeOf(score: number): Grade;
41
+ /** True if `actual` is at least as good as `minimum`. */
42
+ declare function meetsGrade(actual: Grade, minimum: Grade): boolean;
43
+ declare function isGrade(value: string): value is Grade;
44
+
45
+ interface FormatOptions {
46
+ /** Include the concrete attack scenario under each failing header. */
47
+ explain?: boolean;
48
+ }
49
+ declare function formatReport(report: Report, options?: FormatOptions): string;
50
+
51
+ /**
52
+ * Generate an Express (helmet) snippet that fixes everything the report
53
+ * flagged. Only includes config for headers that aren't already passing,
54
+ * so the snippet is a minimal diff against the user's current setup.
55
+ */
56
+ declare function generateExpress(report: Report): string;
57
+
58
+ /**
59
+ * Generate an nginx `server {}` block fragment that fixes everything the
60
+ * report flagged. `always` makes the headers apply to error responses too.
61
+ */
62
+ declare function generateNginx(report: Report): string;
63
+
64
+ export { CheckResult, EXPLOITS, type FormatOptions, Grade, Headers, RECOMMENDED, Report, Rule, ScanContext, formatReport, generateExpress, generateNginx, gradeHeaders, gradeOf, isGrade, isLocalHttpUrl, meetsGrade, rules, runRules, scan, scoreOf };
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ import {
2
+ generateExpress,
3
+ generateNginx
4
+ } from "./chunk-IW5F2ZYM.js";
5
+ import {
6
+ headerGrader
7
+ } from "./chunk-O3B2LYGP.js";
8
+ import {
9
+ EXPLOITS,
10
+ RECOMMENDED,
11
+ formatReport,
12
+ gradeHeaders,
13
+ gradeOf,
14
+ isGrade,
15
+ isLocalHttpUrl,
16
+ meetsGrade,
17
+ rules,
18
+ runRules,
19
+ scan,
20
+ scoreOf
21
+ } from "./chunk-GQYXZFYW.js";
22
+ export {
23
+ EXPLOITS,
24
+ RECOMMENDED,
25
+ formatReport,
26
+ generateExpress,
27
+ generateNginx,
28
+ gradeHeaders,
29
+ gradeOf,
30
+ headerGrader,
31
+ isGrade,
32
+ isLocalHttpUrl,
33
+ meetsGrade,
34
+ rules,
35
+ runRules,
36
+ scan,
37
+ scoreOf
38
+ };
@@ -0,0 +1,64 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+
3
+ /** Lowercased header name → value. Multi-value headers are comma-joined. */
4
+ type Headers = Record<string, string>;
5
+ type Status = "pass" | "warn" | "fail";
6
+ interface CheckResult {
7
+ /** Canonical header name, e.g. "Content-Security-Policy" */
8
+ header: string;
9
+ status: Status;
10
+ /** Human explanation of what was found (or not). */
11
+ message: string;
12
+ /** Points earned toward the score. */
13
+ earned: number;
14
+ /** Max points this rule is worth. 0 for penalty-only rules. */
15
+ weight: number;
16
+ /** The value we recommend setting, when status != pass. */
17
+ recommended?: string;
18
+ /** Concrete attack scenario this header prevents, when status != pass. */
19
+ exploit?: string;
20
+ }
21
+ interface ScanContext {
22
+ headers: Headers;
23
+ /** True when the target is plain HTTP on localhost — dev mode. */
24
+ isLocalHttp: boolean;
25
+ }
26
+ interface Rule {
27
+ header: string;
28
+ weight: number;
29
+ check(ctx: ScanContext): CheckResult;
30
+ }
31
+ type Grade = "A+" | "A" | "B" | "C" | "D" | "F";
32
+ interface Report {
33
+ url: string;
34
+ grade: Grade;
35
+ /** 0–100 */
36
+ score: number;
37
+ results: CheckResult[];
38
+ fetchedAt: string;
39
+ }
40
+
41
+ interface MiddlewareOptions {
42
+ /**
43
+ * Grade every response, deduped by grade — reprints only when the grade
44
+ * changes. Default: grade only the first HTML/document response.
45
+ */
46
+ watch?: boolean;
47
+ /** Include the attack scenario for each failing header in the printed report. */
48
+ explain?: boolean;
49
+ /** Called with the report instead of printing to the console. */
50
+ onReport?: (report: Report) => void;
51
+ /** Treat the server as local HTTP (relaxes HSTS). Default: true — it's a dev tool. */
52
+ isLocalHttp?: boolean;
53
+ }
54
+ /**
55
+ * Express/Connect-compatible middleware that grades the security headers
56
+ * your own app actually sends. Mount it AFTER helmet/header middleware so
57
+ * it sees the final headers:
58
+ *
59
+ * app.use(helmet());
60
+ * if (app.get("env") === "development") app.use(headerGrader());
61
+ */
62
+ declare function headerGrader(options?: MiddlewareOptions): (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void;
63
+
64
+ export { type CheckResult as C, type Grade as G, type Headers as H, type MiddlewareOptions as M, type Report as R, type ScanContext as S, type Rule as a, type Status as b, headerGrader as h };
@@ -0,0 +1,64 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+
3
+ /** Lowercased header name → value. Multi-value headers are comma-joined. */
4
+ type Headers = Record<string, string>;
5
+ type Status = "pass" | "warn" | "fail";
6
+ interface CheckResult {
7
+ /** Canonical header name, e.g. "Content-Security-Policy" */
8
+ header: string;
9
+ status: Status;
10
+ /** Human explanation of what was found (or not). */
11
+ message: string;
12
+ /** Points earned toward the score. */
13
+ earned: number;
14
+ /** Max points this rule is worth. 0 for penalty-only rules. */
15
+ weight: number;
16
+ /** The value we recommend setting, when status != pass. */
17
+ recommended?: string;
18
+ /** Concrete attack scenario this header prevents, when status != pass. */
19
+ exploit?: string;
20
+ }
21
+ interface ScanContext {
22
+ headers: Headers;
23
+ /** True when the target is plain HTTP on localhost — dev mode. */
24
+ isLocalHttp: boolean;
25
+ }
26
+ interface Rule {
27
+ header: string;
28
+ weight: number;
29
+ check(ctx: ScanContext): CheckResult;
30
+ }
31
+ type Grade = "A+" | "A" | "B" | "C" | "D" | "F";
32
+ interface Report {
33
+ url: string;
34
+ grade: Grade;
35
+ /** 0–100 */
36
+ score: number;
37
+ results: CheckResult[];
38
+ fetchedAt: string;
39
+ }
40
+
41
+ interface MiddlewareOptions {
42
+ /**
43
+ * Grade every response, deduped by grade — reprints only when the grade
44
+ * changes. Default: grade only the first HTML/document response.
45
+ */
46
+ watch?: boolean;
47
+ /** Include the attack scenario for each failing header in the printed report. */
48
+ explain?: boolean;
49
+ /** Called with the report instead of printing to the console. */
50
+ onReport?: (report: Report) => void;
51
+ /** Treat the server as local HTTP (relaxes HSTS). Default: true — it's a dev tool. */
52
+ isLocalHttp?: boolean;
53
+ }
54
+ /**
55
+ * Express/Connect-compatible middleware that grades the security headers
56
+ * your own app actually sends. Mount it AFTER helmet/header middleware so
57
+ * it sees the final headers:
58
+ *
59
+ * app.use(helmet());
60
+ * if (app.get("env") === "development") app.use(headerGrader());
61
+ */
62
+ declare function headerGrader(options?: MiddlewareOptions): (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void;
63
+
64
+ export { type CheckResult as C, type Grade as G, type Headers as H, type MiddlewareOptions as M, type Report as R, type ScanContext as S, type Rule as a, type Status as b, headerGrader as h };