drheaderplus 3.0.0__tar.gz

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.
Files changed (76) hide show
  1. drheaderplus-3.0.0/.dockerignore +106 -0
  2. drheaderplus-3.0.0/.editorconfig +24 -0
  3. drheaderplus-3.0.0/.github/FUNDING.yml +3 -0
  4. drheaderplus-3.0.0/.github/ISSUE_TEMPLATE +15 -0
  5. drheaderplus-3.0.0/.github/PULL_REQUEST_TEMPLATE.md +48 -0
  6. drheaderplus-3.0.0/.github/dependabot.yml +23 -0
  7. drheaderplus-3.0.0/.github/workflows/codeql-analysis.yml +37 -0
  8. drheaderplus-3.0.0/.github/workflows/pull_request.yml +53 -0
  9. drheaderplus-3.0.0/.github/workflows/release.yml +36 -0
  10. drheaderplus-3.0.0/.gitignore +115 -0
  11. drheaderplus-3.0.0/CLI.md +242 -0
  12. drheaderplus-3.0.0/CODE_OF_CONDUCT.md +128 -0
  13. drheaderplus-3.0.0/CONTRIBUTING.md +129 -0
  14. drheaderplus-3.0.0/Dockerfile +9 -0
  15. drheaderplus-3.0.0/HISTORY.md +5 -0
  16. drheaderplus-3.0.0/LICENSE +21 -0
  17. drheaderplus-3.0.0/Makefile +12 -0
  18. drheaderplus-3.0.0/PKG-INFO +136 -0
  19. drheaderplus-3.0.0/README.md +101 -0
  20. drheaderplus-3.0.0/RULES.md +408 -0
  21. drheaderplus-3.0.0/SECURITY.md +16 -0
  22. drheaderplus-3.0.0/assets/img/drheaderscansingle.png +0 -0
  23. drheaderplus-3.0.0/assets/img/drheaderscansinglejson.png +0 -0
  24. drheaderplus-3.0.0/assets/img/hero.png +0 -0
  25. drheaderplus-3.0.0/docs/Makefile +20 -0
  26. drheaderplus-3.0.0/docs/_static/.keep +0 -0
  27. drheaderplus-3.0.0/docs/conf.py +169 -0
  28. drheaderplus-3.0.0/docs/contributing.rst +4 -0
  29. drheaderplus-3.0.0/docs/drheader.rst +45 -0
  30. drheaderplus-3.0.0/docs/history.rst +4 -0
  31. drheaderplus-3.0.0/docs/index.rst +19 -0
  32. drheaderplus-3.0.0/docs/installation.rst +66 -0
  33. drheaderplus-3.0.0/docs/make.bat +36 -0
  34. drheaderplus-3.0.0/docs/modules.rst +7 -0
  35. drheaderplus-3.0.0/docs/readme.rst +4 -0
  36. drheaderplus-3.0.0/docs/usage.rst +33 -0
  37. drheaderplus-3.0.0/drheader/__init__.py +4 -0
  38. drheaderplus-3.0.0/drheader/cli/__init__.py +0 -0
  39. drheaderplus-3.0.0/drheader/cli/cli.py +252 -0
  40. drheaderplus-3.0.0/drheader/cli/utils.py +58 -0
  41. drheaderplus-3.0.0/drheader/core.py +185 -0
  42. drheaderplus-3.0.0/drheader/report.py +70 -0
  43. drheaderplus-3.0.0/drheader/resources/cli/bulk_compare_schema.json +20 -0
  44. drheaderplus-3.0.0/drheader/resources/cli/bulk_scan_schema.json +52 -0
  45. drheaderplus-3.0.0/drheader/resources/delimiters.json +40 -0
  46. drheaderplus-3.0.0/drheader/resources/rules.yml +66 -0
  47. drheaderplus-3.0.0/drheader/utils.py +99 -0
  48. drheaderplus-3.0.0/drheader/validators/__init__.py +0 -0
  49. drheaderplus-3.0.0/drheader/validators/base.py +134 -0
  50. drheaderplus-3.0.0/drheader/validators/cookie_validator.py +118 -0
  51. drheaderplus-3.0.0/drheader/validators/directive_validator.py +173 -0
  52. drheaderplus-3.0.0/drheader/validators/header_validator.py +207 -0
  53. drheaderplus-3.0.0/drheader.rst +45 -0
  54. drheaderplus-3.0.0/modules.rst +7 -0
  55. drheaderplus-3.0.0/pyproject.toml +72 -0
  56. drheaderplus-3.0.0/tests/__init__.py +0 -0
  57. drheaderplus-3.0.0/tests/integration_tests/__init__.py +0 -0
  58. drheaderplus-3.0.0/tests/integration_tests/test_cli.py +142 -0
  59. drheaderplus-3.0.0/tests/integration_tests/test_drheader.py +334 -0
  60. drheaderplus-3.0.0/tests/integration_tests/test_rules.py +335 -0
  61. drheaderplus-3.0.0/tests/integration_tests/utils.py +58 -0
  62. drheaderplus-3.0.0/tests/test_resources/bulk_scan.json +11 -0
  63. drheaderplus-3.0.0/tests/test_resources/bulk_scan.txt +3 -0
  64. drheaderplus-3.0.0/tests/test_resources/custom_rules.yml +7 -0
  65. drheaderplus-3.0.0/tests/test_resources/custom_rules_merged.yml +60 -0
  66. drheaderplus-3.0.0/tests/test_resources/default_rules.yml +66 -0
  67. drheaderplus-3.0.0/tests/test_resources/headers_bulk_ko.json +35 -0
  68. drheaderplus-3.0.0/tests/test_resources/headers_bulk_ok.json +44 -0
  69. drheaderplus-3.0.0/tests/test_resources/headers_ko.json +13 -0
  70. drheaderplus-3.0.0/tests/test_resources/headers_ok.json +15 -0
  71. drheaderplus-3.0.0/tests/test_resources/report.json +97 -0
  72. drheaderplus-3.0.0/tests/unit_tests/__init__.py +0 -0
  73. drheaderplus-3.0.0/tests/unit_tests/test_cli.py +219 -0
  74. drheaderplus-3.0.0/tests/unit_tests/test_utils.py +90 -0
  75. drheaderplus-3.0.0/tests/unit_tests/test_validators.py +173 -0
  76. drheaderplus-3.0.0/uv.lock +887 -0
@@ -0,0 +1,106 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ env/
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+
28
+ # PyInstaller
29
+ # Usually these files are written by a python script from a template
30
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ .hypothesis/
48
+ .pytest_cache/
49
+ reports/
50
+
51
+ # Translations
52
+ *.mo
53
+ *.pot
54
+
55
+ # Django stuff:
56
+ *.log
57
+ local_settings.py
58
+
59
+ # Flask stuff:
60
+ instance/
61
+ .webassets-cache
62
+
63
+ # Scrapy stuff:
64
+ .scrapy
65
+
66
+ # Sphinx documentation
67
+ docs/_build/
68
+
69
+ # PyBuilder
70
+ target/
71
+
72
+ # Jupyter Notebook
73
+ .ipynb_checkpoints
74
+
75
+ # pyenv
76
+ .python-version
77
+
78
+ # celery beat schedule file
79
+ celerybeat-schedule
80
+
81
+ # SageMath parsed files
82
+ *.sage.py
83
+
84
+ # dotenv
85
+ .env
86
+
87
+ # virtualenv
88
+ .venv
89
+ venv/
90
+ ENV/
91
+
92
+ # Spyder project settings
93
+ .spyderproject
94
+ .spyproject
95
+
96
+ # Rope project settings
97
+ .ropeproject
98
+
99
+ # mkdocs documentation
100
+ /site
101
+
102
+ # mypy
103
+ .mypy_cache/
104
+
105
+ # jetbrains
106
+ .idea/
@@ -0,0 +1,24 @@
1
+ # http://editorconfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 4
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+ charset = utf-8
11
+ end_of_line = lf
12
+
13
+ [.github/**/*.yml]
14
+ indent_size = 2
15
+
16
+ [*.bat]
17
+ indent_style = tab
18
+ end_of_line = crlf
19
+
20
+ [LICENSE]
21
+ insert_final_newline = false
22
+
23
+ [Makefile]
24
+ indent_style = tab
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ custom: 'https://www.santandertechnology.co.uk'
@@ -0,0 +1,15 @@
1
+ * drHEADer version:
2
+ * Python version:
3
+ * Operating System:
4
+
5
+ ### Description
6
+
7
+ Describe what you were trying to get done.
8
+ Tell us what happened, what went wrong, and what you expected to happen.
9
+
10
+ ### What I Did
11
+
12
+ ```
13
+ Paste the command(s) you ran and the output.
14
+ If there was a crash, please include the traceback here.
15
+ ```
@@ -0,0 +1,48 @@
1
+ # Thank you for contributing to DrHeader !
2
+
3
+ To help keep changes flowing in and avoid potential merging headaches we have created this form.
4
+
5
+ Please fill it in if you can or feel free to ask questions , we don't want this to be a barrier.
6
+
7
+ Please trim above here.
8
+
9
+ ## Proposed changes
10
+
11
+ Please describe your changes here
12
+
13
+ ## Type of change
14
+
15
+ What types of changes do you want to introduce to DrHeader?
16
+
17
+ - [ ] Bugfix (non-breaking change which fixes an issue)
18
+ - [ ] New feature (non-breaking change which adds functionality)
19
+ - [ ] Breaking change
20
+ - [ ] Documentation Update
21
+ - [ ] Test Update
22
+ - [ ] Rules Update
23
+ - [ ] Other (please describe)
24
+
25
+ Please ensure your pull request adheres to the following guidelines:
26
+ - [ ] A Github Issue that explains the work.
27
+ - [ ] The changes are in a branch that is reasonably up to date
28
+ - [ ] Tests are provided to reasonably cover new or altered functionality.
29
+ - [ ] Documentation is provided for the new or altered functionality.
30
+ - [ ] You have the legal right to give us this code.
31
+ - [ ] You have adhered to the CoC
32
+
33
+ ## Link to the github issue
34
+
35
+ https://github.com/Santandersecurityresearch/DrHeader/issues/
36
+
37
+ ## Tests you have added
38
+
39
+ testclass.method_name()
40
+
41
+ ## Tests you have altered
42
+
43
+ testclass.method_name()
44
+
45
+ ## Anything Else
46
+
47
+
48
+ Thanks for getting this far !
@@ -0,0 +1,23 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ versioning-strategy: "lockfile-only"
6
+ schedule:
7
+ interval: "daily"
8
+ target-branch: "develop"
9
+ reviewers:
10
+ - "danielcuthbert"
11
+ - "javixeneize"
12
+ - "pealtrufo"
13
+ - "emilejq"
14
+ - package-ecosystem: "github-actions"
15
+ directory: "/"
16
+ schedule:
17
+ interval: "weekly"
18
+ target-branch: "develop"
19
+ reviewers:
20
+ - "danielcuthbert"
21
+ - "javixeneize"
22
+ - "pealtrufo"
23
+ - "emilejq"
@@ -0,0 +1,37 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+ schedule:
11
+ - cron: "24 23 * * 5"
12
+
13
+ jobs:
14
+ analyze:
15
+ name: Analyze
16
+ runs-on: ubuntu-latest
17
+
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ language:
22
+ - python
23
+
24
+ steps:
25
+ - name: Checkout repository
26
+ uses: actions/checkout@v5
27
+
28
+ - name: Initialize CodeQL
29
+ uses: github/codeql-action/init@v3
30
+ with:
31
+ languages: ${{ matrix.language }}
32
+
33
+ - name: Autobuild
34
+ uses: github/codeql-action/autobuild@v3
35
+
36
+ - name: Perform CodeQL Analysis
37
+ uses: github/codeql-action/analyze@v3
@@ -0,0 +1,53 @@
1
+ name: Scan pull request
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v5
14
+
15
+ - name: Set up uv
16
+ uses: astral-sh/setup-uv@v7
17
+ with:
18
+ python-version: "3.12"
19
+ enable-cache: true
20
+
21
+ - name: Run lint scan
22
+ run: uv run ruff check .
23
+
24
+ - name: Run SAST scan
25
+ run: uv run ruff check ./drheader --select S
26
+
27
+ test:
28
+ runs-on: ubuntu-latest
29
+ strategy:
30
+ matrix:
31
+ python-version:
32
+ - "3.12"
33
+ - "3.13"
34
+
35
+ steps:
36
+ - name: Checkout code
37
+ uses: actions/checkout@v5
38
+
39
+ - name: Set up uv
40
+ uses: astral-sh/setup-uv@v7
41
+ with:
42
+ python-version: ${{ matrix.python-version }}
43
+ enable-cache: true
44
+
45
+ - name: Run tests
46
+ run: uv run pytest --cov=drheader --cov-fail-under=80 --junitxml results.xml
47
+
48
+ - name: Upload test results
49
+ uses: actions/upload-artifact@v4
50
+ if: always()
51
+ with:
52
+ name: results-${{ matrix.python-version }}
53
+ path: results.xml
@@ -0,0 +1,36 @@
1
+ name: Create release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+
12
+ permissions:
13
+ contents: write
14
+ id-token: write
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v5
19
+
20
+ - name: Set up uv
21
+ uses: astral-sh/setup-uv@v7
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ - name: Build release artifacts
26
+ run: uv build
27
+
28
+ - name: Create GitHub release
29
+ uses: ncipollo/release-action@v1
30
+ with:
31
+ artifacts: dist/*
32
+ generateReleaseNotes: true
33
+
34
+ # TODO (Phase 4): Set up trusted publishing on PyPI, then uncomment:
35
+ # - name: Publish to PyPI
36
+ # run: uv publish
@@ -0,0 +1,115 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # local development files
10
+ .claude/
11
+ .vscode/
12
+ work_docs/
13
+
14
+ # Distribution / packaging
15
+ .Python
16
+ env/
17
+ build/
18
+ develop-eggs/
19
+ dist/
20
+ downloads/
21
+ eggs/
22
+ .eggs/
23
+ lib/
24
+ lib64/
25
+ parts/
26
+ sdist/
27
+ var/
28
+ wheels/
29
+ *.egg-info/
30
+ .installed.cfg
31
+ *.egg
32
+
33
+ # PyInstaller
34
+ # Usually these files are written by a python script from a template
35
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
36
+ *.manifest
37
+ *.spec
38
+
39
+ # Installer logs
40
+ pip-log.txt
41
+ pip-delete-this-directory.txt
42
+
43
+ # Unit test / coverage reports
44
+ htmlcov/
45
+ .tox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+
63
+ # Flask stuff:
64
+ instance/
65
+ .webassets-cache
66
+
67
+ # Scrapy stuff:
68
+ .scrapy
69
+
70
+ # Sphinx documentation
71
+ docs/_build/
72
+ docs/_static/*
73
+ !docs/_static/.keep
74
+
75
+ # PyBuilder
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # pyenv
82
+ .python-version
83
+
84
+ # celery beat schedule file
85
+ celerybeat-schedule
86
+
87
+ # SageMath parsed files
88
+ *.sage.py
89
+
90
+ # dotenv
91
+ .env
92
+
93
+ # virtualenv
94
+ .venv
95
+ venv/
96
+ ENV/
97
+
98
+ # Spyder project settings
99
+ .spyderproject
100
+ .spyproject
101
+
102
+ # Rope project settings
103
+ .ropeproject
104
+
105
+ # mkdocs documentation
106
+ /site
107
+
108
+ # mypy
109
+ .mypy_cache/
110
+
111
+ # jetbrains
112
+ .idea/
113
+
114
+ # junit reports folder
115
+ reports
@@ -0,0 +1,242 @@
1
+ ![drHEADer](assets/img/hero.png)
2
+
3
+ # CLI Usage
4
+ This page describes how to use the drHEADer command line interface.
5
+
6
+ ## Contents
7
+ * [Analysing Headers Locally](#analysing-headers-locally)
8
+ * [Bulk Scanning](#bulk-scanning)
9
+ * [Scan Options](#scan-options)
10
+ * [Scanning Remote Endpoints](#scanning-remote-endpoints)
11
+ * [Configuring the HTTP Request](#configuring-the-http-request)
12
+ * [Bulk Scanning](#bulk-scanning-1)
13
+ * [File Input Format](#file-input-format)
14
+ * [Configuring the HTTP Request](#configuring-the-http-request-1)
15
+ * [Scan Options](#scan-options-1)
16
+ * [Report Output](#report-output)
17
+
18
+ ## Analysing Headers Locally
19
+ You can validate a set of headers against a drHEADer ruleset using the `compare single` command:
20
+ ```shell
21
+ $ drheader compare single [SCAN_OPTIONS] FILE
22
+ ```
23
+
24
+ This will parse the contents of `FILE`, analyse the headers within it against a drHEADer ruleset, and report back any
25
+ rule violations. `FILE` is the path to a JSON file containing the headers to be analysed.
26
+
27
+ ### Bulk Scanning
28
+ You can validate several sets of headers at once using the `compare bulk` command:
29
+ ```shell
30
+ $ drheader compare bulk [SCAN_OPTIONS] FILE
31
+ ```
32
+
33
+ The contents of `FILE` must be a JSON array with each item specifying a set of headers to be analysed and an associated
34
+ endpoint:
35
+
36
+ ```json
37
+ [
38
+ {
39
+ "url": "https://example.com",
40
+ "headers": {
41
+ "Cache-Control": "private, must-revalidate",
42
+ "Content-Security-Policy": "default-src 'self'; script-src 'unsafe-inline'"
43
+ }
44
+ },
45
+ {
46
+ "url": "https://example.net",
47
+ "headers": {
48
+ "Referrer-Policy": "strict-origin",
49
+ "Strict-Transport-Security": "max-age=31536000; preload",
50
+ "X-Content-Type-Options": "nosniff"
51
+ }
52
+ }
53
+ ]
54
+ ```
55
+
56
+ You can view the JSON schema for bulk scanning with `compare` [here](drheader/resources/cli/bulk_compare_schema.json).
57
+
58
+ ### Scan Options
59
+ This table lists the scan options available when using the `compare` command:
60
+
61
+ | Option | Shorthand Option | Description |
62
+ |:---------------------------|:-----------------|:------------------------------------------------------------|
63
+ | `--cross-origin-isolated` | `-co` | Enable cross-origin isolation validations ¹ |
64
+ | `--debug` | `-d` | Enable debug logging |
65
+ | `--junit` | `-j` | Generate a JUnit report *(not available for bulk scanning)* |
66
+ | `--merge` | `-m` | Merge a custom ruleset with the default rules |
67
+ | `--output [json \| table]` | `-o` | Report output format [default: table] |
68
+ | `--rules-file FILENAME` | `-rf` | Use a custom ruleset, loaded from file ² |
69
+ | `--rules-uri URI` | `-ru` | Use a custom ruleset, downloaded from URI ² |
70
+
71
+ ¹ Cross-origin isolation validations are opt-in. See [Cross-Origin Isolation](README.md#cross-origin-isolation).
72
+
73
+ ² For information on defining a custom ruleset see [RULES](RULES.md).
74
+
75
+ ## Scanning Remote Endpoints
76
+ You can scan a remote endpoint using the `scan single` command:
77
+
78
+ ```shell
79
+ $ drheader scan single [SCAN_OPTIONS] TARGET_URL [REQUEST_ARGS]
80
+ ```
81
+
82
+ This will send an HTTP `HEAD` request to `TARGET_URL`, validate the headers that are returned in the response and report
83
+ back any rule violations.
84
+
85
+ ### Configuring the HTTP Request
86
+ Internally, drHEADer uses the [`requests`](https://requests.readthedocs.io/en/latest/) package to make the HTTP call,
87
+ and you can customise the request with the same configuration options that can be processed by this package. Any
88
+ arguments received in `[REQUEST_ARGS]` will be propagated to the HTTP call. This means, you can for instance...
89
+
90
+ * Change the request method:
91
+ ```shell
92
+ $ drheader scan single https://example.com --method POST
93
+ ```
94
+
95
+ * Send request parameters:
96
+ ```shell
97
+ $ drheader scan single https://example.com --params '{"name": "h_simpson", "department": "Sector 7G"}'
98
+ ```
99
+
100
+ * Send data in the request body:
101
+ ```shell
102
+ $ drheader scan single https://example.com --json '{"number": "42", "street": "Wallaby Way", "city": "Sydney"}'
103
+ ```
104
+
105
+ * Configure the timeout on the request:
106
+ ```shell
107
+ $ drheader scan single https://example.com --timeout 30
108
+ $ drheader scan single https://example.com --timeout '(5, 30)'
109
+ ```
110
+
111
+ * Configure SSL verification:
112
+ ```shell
113
+ $ drheader scan single https://example.com --verify false
114
+ $ drheader scan single https://example.com --verify 'path/to/ca/bundle'
115
+ ```
116
+
117
+ See the [requests](https://requests.readthedocs.io/en/latest/_modules/requests/api/#request) documentation for a full
118
+ list of options.
119
+
120
+ ### Bulk Scanning
121
+ You can scan several endpoints at once using the `scan bulk` command:
122
+ ```shell
123
+ $ drheader scan bulk [SCAN_OPTIONS] FILE
124
+ ```
125
+
126
+ The contents of `FILE` must be a JSON array with each item specifying a URL to target and additional request args:
127
+ ```json
128
+ [
129
+ {
130
+ "url": "https://example.com"
131
+ },
132
+ {
133
+ "url": "https://example.net"
134
+ },
135
+ {
136
+ "url": "https://example.org"
137
+ }
138
+ ]
139
+ ```
140
+
141
+ You can view the JSON schema for bulk scanning with `scan` [here](drheader/resources/cli/bulk_scan_schema.json). See
142
+ [configuring the HTTP request](#configuring-the-http-request-1) for details on request args.
143
+
144
+ #### File Input Format
145
+ The default input format for `FILE` is JSON, which allows you to configure more complex HTTP requests (see
146
+ [configuring the HTTP request](#configuring-the-http-request-1)). If you only want to target each endpoint with a basic
147
+ HTTP HEAD request and no additional configuration, you can choose to pass the input file in a simpler `.txt` format by
148
+ specifying the `-ff` (file format) option:
149
+
150
+ ```shell
151
+ $ drheader scan bulk -ff txt FILE
152
+ ```
153
+
154
+ Each endpoint must be on a separate line:
155
+ ```
156
+ https://example.com
157
+ https://example.net
158
+ https://example.org
159
+ ```
160
+
161
+ #### Configuring the HTTP Request
162
+ For bulk scanning, [request args](#configuring-the-http-request) are configured on a per-target basis in the JSON file:
163
+ ```json
164
+ [
165
+ {
166
+ "url": "https://example.com",
167
+ "method": "POST"
168
+ },
169
+ {
170
+ "url": "https://example.net",
171
+ "params": {
172
+ "name": "h_simpson",
173
+ "department": "Sector 7G"
174
+ }
175
+ },
176
+ {
177
+ "url": "https://example.org",
178
+ "json": {
179
+ "number": "42",
180
+ "street": "Wallaby Way",
181
+ "city": "Sydney"
182
+ },
183
+ "timeout": 30,
184
+ "verify": false
185
+ }
186
+ ]
187
+ ```
188
+
189
+ See the [requests](https://requests.readthedocs.io/en/latest/_modules/requests/api/#request) documentation for a full
190
+ list of options.
191
+
192
+ ### Scan Options
193
+ This table lists the scan options available when using the `scan` command:
194
+
195
+ | Option | Shorthand Option | Description |
196
+ |:------------------------------|:-----------------|:------------------------------------------------------------|
197
+ | `--cross-origin-isolated` | `-co` | Enable cross-origin isolation validations ¹ |
198
+ | `--debug` | `-d` | Enable debug logging |
199
+ | `--file-format [json \| txt]` | `-ff` | FILE input format [default: json] *(bulk scanning only)* |
200
+ | `--junit` | `-j` | Generate a JUnit report *(not available for bulk scanning)* |
201
+ | `--merge` | `-m` | Merge a custom ruleset with the default rules |
202
+ | `--output [json \| table]` | `-o` | Report output format [default: table] |
203
+ | `--rules-file FILENAME` | `-rf` | Use a custom ruleset, loaded from file ² |
204
+ | `--rules-uri URI` | `-ru` | Use a custom ruleset, downloaded from URI ² |
205
+
206
+ ¹ Cross-origin isolation validations are opt-in. See [Cross-Origin Isolation](README.md#cross-origin-isolation).
207
+
208
+ ² For information on defining a custom ruleset see [RULES](RULES.md).
209
+
210
+ ## Report Output
211
+ By default, results will be output in a tabulated format:
212
+
213
+ ```
214
+ https://example.com: 9 issues found
215
+ ----
216
+ rule | Cache-Control
217
+ message | Value does not match security policy
218
+ severity | high
219
+ value | max-age=604800
220
+ expected | ['no-store', 'max-age=0']
221
+ delimiter | ,
222
+ ----
223
+ rule | Content-Security-Policy
224
+ message | Header not included in response
225
+ severity | high
226
+ ----
227
+ rule | Pragma
228
+ message | Header not included in response
229
+ severity | high
230
+ expected | ['no-cache']
231
+ ```
232
+
233
+ You can change this using the `--output` option. Currently, the only other supported option is JSON:
234
+ ```sh
235
+ $ drheader scan single --output json
236
+ ```
237
+
238
+ In order to save scan results, you can pipe the JSON output to [jq](https://stedolan.github.io/jq/), which is a
239
+ lightweight and flexible command-line JSON processor:
240
+ ```sh
241
+ $ drheader scan single --output json https://example.com | jq '.'
242
+ ```