header-grader 0.1.0 → 0.1.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 CHANGED
@@ -290,13 +290,23 @@ npm run typecheck # tsc --noEmit
290
290
  npm run build # tsup → dist/ (ESM + CJS + .d.ts)
291
291
  ```
292
292
 
293
- Try it against a deliberately bad server:
293
+ No server handy? The repo ships two sample servers (also used as CI fixtures):
294
294
 
295
295
  ```sh
296
- node -e 'require("http").createServer((q,s)=>{s.setHeader("Content-Type","text/html");s.end("hi")}).listen(3456)' &
297
- node dist/cli.js localhost:3456 --fix express
296
+ npm run demo:bare # unhardened server on :3456, grades F
297
+ npm run demo:hardened # fully hardened server on :3457, grades A+
298
298
  ```
299
299
 
300
+ Then, in another terminal:
301
+
302
+ ```sh
303
+ node dist/cli.js localhost:3456 --explain # see the F and why it matters
304
+ node dist/cli.js localhost:3456 --fix express # see the generated fix
305
+ node dist/cli.js localhost:3457 # see what A+ looks like
306
+ ```
307
+
308
+ A note on grading real-world sites: header-grader evaluates exactly what the response sends, so even big-name production sites can score poorly. Some of that is deliberate tradeoff (for example, a domain baked into the browser HSTS preload list gains little from the HSTS header, and a Content-Security-Policy-Report-Only header monitors without enforcing, which earns partial credit here). The rubric is tuned for what YOUR app should send, not for excusing what large platforms can get away with.
309
+
300
310
  ## Roadmap
301
311
 
302
312
  - [ ] Caddy and Apache config generators
@@ -39,6 +39,15 @@ var csp = {
39
39
  check(ctx) {
40
40
  const value = ctx.headers["content-security-policy"];
41
41
  if (!value) {
42
+ if (ctx.headers["content-security-policy-report-only"]) {
43
+ return result(
44
+ this,
45
+ "warn",
46
+ "Only Content-Security-Policy-Report-Only is set. Violations are reported but nothing is blocked; promote the policy to the enforcing header once the reports are clean.",
47
+ 0.25,
48
+ RECOMMENDED["Content-Security-Policy"]
49
+ );
50
+ }
42
51
  return result(
43
52
  this,
44
53
  "fail",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  formatReport,
3
3
  gradeHeaders
4
- } from "./chunk-GQYXZFYW.js";
4
+ } from "./chunk-CUWFMOK7.js";
5
5
 
6
6
  // src/middleware.ts
7
7
  function headerGrader(options = {}) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RECOMMENDED
3
- } from "./chunk-GQYXZFYW.js";
3
+ } from "./chunk-CUWFMOK7.js";
4
4
 
5
5
  // src/generators/express.ts
6
6
  function generateExpress(report) {
package/dist/cli.cjs CHANGED
@@ -42,6 +42,15 @@ var csp = {
42
42
  check(ctx) {
43
43
  const value = ctx.headers["content-security-policy"];
44
44
  if (!value) {
45
+ if (ctx.headers["content-security-policy-report-only"]) {
46
+ return result(
47
+ this,
48
+ "warn",
49
+ "Only Content-Security-Policy-Report-Only is set. Violations are reported but nothing is blocked; promote the policy to the enforcing header once the reports are clean.",
50
+ 0.25,
51
+ RECOMMENDED["Content-Security-Policy"]
52
+ );
53
+ }
45
54
  return result(
46
55
  this,
47
56
  "fail",
package/dist/cli.js CHANGED
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  generateExpress,
4
4
  generateNginx
5
- } from "./chunk-IW5F2ZYM.js";
5
+ } from "./chunk-ZLAMK7PS.js";
6
6
  import {
7
7
  formatReport,
8
8
  isGrade,
9
9
  meetsGrade,
10
10
  scan
11
- } from "./chunk-GQYXZFYW.js";
11
+ } from "./chunk-CUWFMOK7.js";
12
12
 
13
13
  // src/cli.ts
14
14
  var HELP = `header-grader \u2014 grade your dev server's security headers
package/dist/index.cjs CHANGED
@@ -79,6 +79,15 @@ var csp = {
79
79
  check(ctx) {
80
80
  const value = ctx.headers["content-security-policy"];
81
81
  if (!value) {
82
+ if (ctx.headers["content-security-policy-report-only"]) {
83
+ return result(
84
+ this,
85
+ "warn",
86
+ "Only Content-Security-Policy-Report-Only is set. Violations are reported but nothing is blocked; promote the policy to the enforcing header once the reports are clean.",
87
+ 0.25,
88
+ RECOMMENDED["Content-Security-Policy"]
89
+ );
90
+ }
82
91
  return result(
83
92
  this,
84
93
  "fail",
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  generateExpress,
3
3
  generateNginx
4
- } from "./chunk-IW5F2ZYM.js";
4
+ } from "./chunk-ZLAMK7PS.js";
5
5
  import {
6
6
  headerGrader
7
- } from "./chunk-O3B2LYGP.js";
7
+ } from "./chunk-YQYAHLR6.js";
8
8
  import {
9
9
  EXPLOITS,
10
10
  RECOMMENDED,
@@ -18,7 +18,7 @@ import {
18
18
  runRules,
19
19
  scan,
20
20
  scoreOf
21
- } from "./chunk-GQYXZFYW.js";
21
+ } from "./chunk-CUWFMOK7.js";
22
22
  export {
23
23
  EXPLOITS,
24
24
  RECOMMENDED,
@@ -66,6 +66,15 @@ var csp = {
66
66
  check(ctx) {
67
67
  const value = ctx.headers["content-security-policy"];
68
68
  if (!value) {
69
+ if (ctx.headers["content-security-policy-report-only"]) {
70
+ return result(
71
+ this,
72
+ "warn",
73
+ "Only Content-Security-Policy-Report-Only is set. Violations are reported but nothing is blocked; promote the policy to the enforcing header once the reports are clean.",
74
+ 0.25,
75
+ RECOMMENDED["Content-Security-Policy"]
76
+ );
77
+ }
69
78
  return result(
70
79
  this,
71
80
  "fail",
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  headerGrader,
3
3
  middleware_default
4
- } from "./chunk-O3B2LYGP.js";
5
- import "./chunk-GQYXZFYW.js";
4
+ } from "./chunk-YQYAHLR6.js";
5
+ import "./chunk-CUWFMOK7.js";
6
6
  export {
7
7
  middleware_default as default,
8
8
  headerGrader
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "header-grader",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Security header grader for local dev — grades your dev server's HTTP security headers and generates the Express/Nginx config to fix them.",
5
5
  "keywords": [
6
6
  "security",
@@ -40,6 +40,9 @@
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsup",
43
+ "demo:bare": "node test/fixtures/bare-server.mjs",
44
+ "demo:hardened": "node test/fixtures/hardened-server.mjs",
45
+ "prepublishOnly": "npm run typecheck && npm test && npm run build",
43
46
  "test": "vitest run",
44
47
  "test:watch": "vitest",
45
48
  "typecheck": "tsc --noEmit"