v2.31.0-dev10 f49cffc

security-hardening-regression-matrix.md RawHistoryFolder

Security Hardening Regression Matrix

This matrix lists the behaviors that should be tested while implementing the security-hardening fixes from the audit. It is intentionally focused on regressions: normal Gordon workflows must continue to work while exploit paths are blocked.

Registry uploads

Normal behavior to preserve

  • Docker push of a small image succeeds.
  • Docker push with multiple layers succeeds when every layer is below the configured cumulative blob limit.
  • Chunked blob upload succeeds when the cumulative size remains below the new cumulative limit setting, tentatively named max_blob_size unless implementation chooses a clearer config name.
  • A final PUT with a valid digest finalizes the blob and returns OCI-compatible headers.
  • Existing max_blob_chunk_size behavior still rejects a single oversized chunk; this remains distinct from the cumulative per-blob/layer limit.

Security behavior to verify

  • Repeated PATCH chunks cannot exceed the cumulative upload limit.
  • Content-Length larger than the remaining allowed size is rejected before writing when possible.
  • A rejected upload does not leave unbounded stale data on disk.
  • Cancel/cleanup paths remove upload temp files and upload locks.
  • Error response remains Docker Registry compatible (413 / SIZE_INVALID).

Suggested tests

  • Unit tests for filesystem blob append under and over cumulative size.
  • Handler tests for PATCH and final PUT over limit.
  • Integration/manual: push image with a large layer and confirm failure is clean.

Deploy errors and logs

Normal behavior to preserve

  • Successful deploy response still includes status, domain, and container ID.
  • Failed deploy still returns useful high-level error/cause/hint.
  • Operators with the new logs permission can still retrieve logs through /admin/logs.
  • CLI deploy displays helpful failure information without leaking raw secrets.

Security behavior to verify

  • A token with only admin:config:write cannot receive raw container logs in /admin/deploy error responses.
  • Logs returned through log endpoints are redacted for common secret patterns.
  • admin:status:read no longer grants log read access.
  • admin:*:* remains compatible and can access logs.

Suggested tests

  • Handler tests for deploy error response with and without logs:read.
  • Scope tests for logs:read, wildcard, and old status:read behavior.
  • Redactor table tests for PASSWORD=, TOKEN=, SECRET=, API_KEY=, DATABASE_URL=, and simple JSON fields.

Admin scopes and compatibility

Normal behavior to preserve

  • Existing admin:*:* tokens continue to work everywhere.
  • Existing routes, config, secrets, and status scopes keep their intended behavior.
  • Token exchange through /auth/token still works for admin scopes.

Security behavior to verify

  • New sensitive resources such as logs and possibly volumes are parsed and enforced.
  • Unknown or malformed scopes remain ignored/denied, not accidentally allowed.

Suggested tests

  • Domain auth scope parsing tests.
  • Admin middleware/handler tests for each sensitive endpoint.

Auto-route env-file extraction

Normal behavior to preserve

  • Valid gordon.env-file imports default env values for a newly created auto-route.
  • Existing env values still override image-provided defaults.
  • Secret reference rejection remains intact.
  • Auto-route without env-file remains unchanged.

Security behavior to verify

  • Oversized env files are rejected before full memory read.
  • Disallowed paths (/proc, /sys, /dev, /run, /var/run, /, traversal) are rejected.
  • Failed env-file import does not prevent route/deploy behavior beyond the intended warning path unless explicitly designed.

Suggested tests

  • Runtime extraction tests using a controlled reader larger than the limit.
  • Auto-route usecase tests for allowed/disallowed paths.
  • Tests confirming ${pass:...} / ${sops:...} refs remain rejected.

Domain canonicalization and proxy routing

Normal behavior to preserve

  • Existing lowercase route domains continue to resolve.
  • Registry domain still routes to registry.
  • External routes still resolve and retain SSRF protections.
  • Hostnames with expected public domains work through proxy.

Security behavior to verify

  • App.Example.com and app.example.com map to the same canonical route.
  • Duplicate case-variant routes cannot be created.
  • Host with invalid port/trailing dot/case is handled consistently.
  • HTTP-to-HTTPS redirect does not reflect arbitrary unconfigured Host values.

Suggested tests

  • Config service tests for add/update/list canonical route domains.
  • Auto-route tests for case variants.
  • Proxy handler tests for Host normalization.
  • Middleware tests for redirect target host validation.

Volumes

Normal behavior to preserve

  • Listing volumes still shows Gordon-managed volumes.
  • Dry-run prune still reports what would be removed.
  • Actual prune still removes unused Gordon-managed volumes.
  • In-use Gordon volumes are not removed.

Security behavior to verify

  • Unused non-Gordon Docker volumes are not removed.
  • Volumes without explicit Gordon ownership metadata, preferably gordon.managed=true, are ignored; prefix-only matching is unsafe except as a constrained legacy fallback with dedicated tests.
  • Any new volumes:read/write scope is enforced correctly.

Suggested tests

  • Volume service tests with mixed Gordon/non-Gordon, used/unused volumes.
  • Admin handler tests for permissions.
  • Manual: create an unrelated Docker volume, run Gordon prune dry-run/real, confirm it remains.

Backups

Normal behavior to preserve

  • Manual backup completes and appears in list.
  • Scheduled backup path format remains readable/listable.
  • Backup detect still finds supported DB attachments.
  • Existing backups can still be listed after filename format changes.

Security behavior to verify

  • Two backups for same domain/db/schedule in the same second do not share tmp/final filenames.
  • Concurrent backups do not truncate each other.
  • Store uses unique tmp files and atomic rename.
  • Path traversal protections remain intact.

Suggested tests

  • Filesystem storage tests with identical timestamps.
  • Concurrent store test with two readers and same domain/db/schedule.
  • List tests for old and new filename formats if compatibility is needed.

Secrets and pass migration

Normal behavior to preserve

  • pass backend still migrates existing env keys correctly.
  • Attachment env migration still works.
  • Unsafe backend still loads valid files under dataDir/secrets for development.
  • Existing env file parsing remains compatible.

Security behavior to verify

  • Unsafe backend rejects ../ and absolute auth.token_secret paths.
  • Migration does not leave plaintext .env.migrated by default.
  • If an explicit keep/quarantine option exists, files are stored with restrictive permissions and loud warnings.

Suggested tests

  • loadSecret path traversal tests.
  • Migration tests verifying plaintext source file removal/quarantine.
  • Permission tests where practical (0600 files, 0700 dirs).

Config snapshot

Normal behavior to preserve

  • /admin/config still returns enough information for CLI/admin use.
  • Routes and network isolation status remain visible to authorized callers.

Security behavior to verify

  • data_dir is hidden by default or only available under a deliberately stronger detailed mode.
  • External route targets are hidden/redacted by default or gated.
  • config:read behavior remains documented.

Suggested tests

  • Admin config response tests for default and detailed modes.
  • CLI remote config tests if output shape changes.

External image registries

Normal behavior to preserve

  • Images in the Gordon registry deploy normally.
  • Explicitly allowlisted external registries deploy if configured.
  • Attachments still deploy from allowed sources.

Security behavior to verify

  • localhost, loopback, private IP, link-local, metadata IP, and DNS resolving to private ranges are rejected unless a deliberate unsafe override exists.
  • Non-allowlisted external registries are rejected before Docker pull.
  • Error messages do not leak sensitive network details.

Suggested tests

  • Image reference validation table tests.
  • Config tests for allowed_registries.
  • Container service tests ensuring rejected images do not call PullImage.

Docker networks and runtime hardening

Normal behavior to preserve

  • Default/compat profile keeps common apps and attachments working.
  • Attachments remain reachable by service alias where intended.
  • Network groups still work when configured.

Security behavior to verify

  • internal network option is applied when configured.
  • Strict profile applies readonly rootfs/user/caps as designed.
  • no-new-privileges:true and cap dropping are preserved.
  • Compat profile behavior is documented and tested.

Suggested tests

  • Docker adapter config construction tests.
  • Container service tests for network option propagation.
  • Manual smoke: deploy app + postgres attachment in compat profile.
  • Manual smoke: deploy simple read-only app in strict profile.

Install, Dockerfile, and supply-chain

Normal behavior to preserve

  • install.sh installs the binary on Linux/macOS.
  • GitHub composite action installs Gordon in CI.
  • Dockerfile builds successfully.

Security behavior to verify

  • Tar extraction only extracts gordon.
  • Installed binary must be a regular file, not symlink/directory.
  • Permissions are explicit (0755).
  • Checksums/signatures are verified consistently.
  • Gitleaks output is clean or only contains allowlisted examples.

Suggested tests

  • Shellcheck/manual review for install script.
  • Action script dry-run if practical.
  • Docker build smoke after version alignment.
  • Gitleaks on git archive HEAD, not local .worktrees.
source
1# Security Hardening Regression Matrix
2
3This matrix lists the behaviors that should be tested while implementing the security-hardening fixes from the audit. It is intentionally focused on regressions: normal Gordon workflows must continue to work while exploit paths are blocked.
4
5## Registry uploads
6
7### Normal behavior to preserve
8- Docker push of a small image succeeds.
9- Docker push with multiple layers succeeds when every layer is below the configured cumulative blob limit.
10- Chunked blob upload succeeds when the cumulative size remains below the new cumulative limit setting, tentatively named `max_blob_size` unless implementation chooses a clearer config name.
11- A final `PUT` with a valid digest finalizes the blob and returns OCI-compatible headers.
12- Existing `max_blob_chunk_size` behavior still rejects a single oversized chunk; this remains distinct from the cumulative per-blob/layer limit.
13
14### Security behavior to verify
15- Repeated `PATCH` chunks cannot exceed the cumulative upload limit.
16- `Content-Length` larger than the remaining allowed size is rejected before writing when possible.
17- A rejected upload does not leave unbounded stale data on disk.
18- Cancel/cleanup paths remove upload temp files and upload locks.
19- Error response remains Docker Registry compatible (`413` / `SIZE_INVALID`).
20
21### Suggested tests
22- Unit tests for filesystem blob append under and over cumulative size.
23- Handler tests for `PATCH` and final `PUT` over limit.
24- Integration/manual: push image with a large layer and confirm failure is clean.
25
26## Deploy errors and logs
27
28### Normal behavior to preserve
29- Successful deploy response still includes status, domain, and container ID.
30- Failed deploy still returns useful high-level error/cause/hint.
31- Operators with the new logs permission can still retrieve logs through `/admin/logs`.
32- CLI deploy displays helpful failure information without leaking raw secrets.
33
34### Security behavior to verify
35- A token with only `admin:config:write` cannot receive raw container logs in `/admin/deploy` error responses.
36- Logs returned through log endpoints are redacted for common secret patterns.
37- `admin:status:read` no longer grants log read access.
38- `admin:*:*` remains compatible and can access logs.
39
40### Suggested tests
41- Handler tests for deploy error response with and without `logs:read`.
42- Scope tests for `logs:read`, wildcard, and old `status:read` behavior.
43- Redactor table tests for `PASSWORD=`, `TOKEN=`, `SECRET=`, `API_KEY=`, `DATABASE_URL=`, and simple JSON fields.
44
45## Admin scopes and compatibility
46
47### Normal behavior to preserve
48- Existing `admin:*:*` tokens continue to work everywhere.
49- Existing `routes`, `config`, `secrets`, and `status` scopes keep their intended behavior.
50- Token exchange through `/auth/token` still works for admin scopes.
51
52### Security behavior to verify
53- New sensitive resources such as `logs` and possibly `volumes` are parsed and enforced.
54- Unknown or malformed scopes remain ignored/denied, not accidentally allowed.
55
56### Suggested tests
57- Domain auth scope parsing tests.
58- Admin middleware/handler tests for each sensitive endpoint.
59
60## Auto-route env-file extraction
61
62### Normal behavior to preserve
63- Valid `gordon.env-file` imports default env values for a newly created auto-route.
64- Existing env values still override image-provided defaults.
65- Secret reference rejection remains intact.
66- Auto-route without env-file remains unchanged.
67
68### Security behavior to verify
69- Oversized env files are rejected before full memory read.
70- Disallowed paths (`/proc`, `/sys`, `/dev`, `/run`, `/var/run`, `/`, traversal) are rejected.
71- Failed env-file import does not prevent route/deploy behavior beyond the intended warning path unless explicitly designed.
72
73### Suggested tests
74- Runtime extraction tests using a controlled reader larger than the limit.
75- Auto-route usecase tests for allowed/disallowed paths.
76- Tests confirming `${pass:...}` / `${sops:...}` refs remain rejected.
77
78## Domain canonicalization and proxy routing
79
80### Normal behavior to preserve
81- Existing lowercase route domains continue to resolve.
82- Registry domain still routes to registry.
83- External routes still resolve and retain SSRF protections.
84- Hostnames with expected public domains work through proxy.
85
86### Security behavior to verify
87- `App.Example.com` and `app.example.com` map to the same canonical route.
88- Duplicate case-variant routes cannot be created.
89- Host with invalid port/trailing dot/case is handled consistently.
90- HTTP-to-HTTPS redirect does not reflect arbitrary unconfigured Host values.
91
92### Suggested tests
93- Config service tests for add/update/list canonical route domains.
94- Auto-route tests for case variants.
95- Proxy handler tests for Host normalization.
96- Middleware tests for redirect target host validation.
97
98## Volumes
99
100### Normal behavior to preserve
101- Listing volumes still shows Gordon-managed volumes.
102- Dry-run prune still reports what would be removed.
103- Actual prune still removes unused Gordon-managed volumes.
104- In-use Gordon volumes are not removed.
105
106### Security behavior to verify
107- Unused non-Gordon Docker volumes are not removed.
108- Volumes without explicit Gordon ownership metadata, preferably `gordon.managed=true`, are ignored; prefix-only matching is unsafe except as a constrained legacy fallback with dedicated tests.
109- Any new `volumes:read/write` scope is enforced correctly.
110
111### Suggested tests
112- Volume service tests with mixed Gordon/non-Gordon, used/unused volumes.
113- Admin handler tests for permissions.
114- Manual: create an unrelated Docker volume, run Gordon prune dry-run/real, confirm it remains.
115
116## Backups
117
118### Normal behavior to preserve
119- Manual backup completes and appears in list.
120- Scheduled backup path format remains readable/listable.
121- Backup detect still finds supported DB attachments.
122- Existing backups can still be listed after filename format changes.
123
124### Security behavior to verify
125- Two backups for same domain/db/schedule in the same second do not share tmp/final filenames.
126- Concurrent backups do not truncate each other.
127- Store uses unique tmp files and atomic rename.
128- Path traversal protections remain intact.
129
130### Suggested tests
131- Filesystem storage tests with identical timestamps.
132- Concurrent store test with two readers and same domain/db/schedule.
133- List tests for old and new filename formats if compatibility is needed.
134
135## Secrets and pass migration
136
137### Normal behavior to preserve
138- `pass` backend still migrates existing env keys correctly.
139- Attachment env migration still works.
140- Unsafe backend still loads valid files under `dataDir/secrets` for development.
141- Existing env file parsing remains compatible.
142
143### Security behavior to verify
144- Unsafe backend rejects `../` and absolute `auth.token_secret` paths.
145- Migration does not leave plaintext `.env.migrated` by default.
146- If an explicit keep/quarantine option exists, files are stored with restrictive permissions and loud warnings.
147
148### Suggested tests
149- `loadSecret` path traversal tests.
150- Migration tests verifying plaintext source file removal/quarantine.
151- Permission tests where practical (`0600` files, `0700` dirs).
152
153## Config snapshot
154
155### Normal behavior to preserve
156- `/admin/config` still returns enough information for CLI/admin use.
157- Routes and network isolation status remain visible to authorized callers.
158
159### Security behavior to verify
160- `data_dir` is hidden by default or only available under a deliberately stronger detailed mode.
161- External route targets are hidden/redacted by default or gated.
162- `config:read` behavior remains documented.
163
164### Suggested tests
165- Admin config response tests for default and detailed modes.
166- CLI remote config tests if output shape changes.
167
168## External image registries
169
170### Normal behavior to preserve
171- Images in the Gordon registry deploy normally.
172- Explicitly allowlisted external registries deploy if configured.
173- Attachments still deploy from allowed sources.
174
175### Security behavior to verify
176- `localhost`, loopback, private IP, link-local, metadata IP, and DNS resolving to private ranges are rejected unless a deliberate unsafe override exists.
177- Non-allowlisted external registries are rejected before Docker pull.
178- Error messages do not leak sensitive network details.
179
180### Suggested tests
181- Image reference validation table tests.
182- Config tests for `allowed_registries`.
183- Container service tests ensuring rejected images do not call `PullImage`.
184
185## Docker networks and runtime hardening
186
187### Normal behavior to preserve
188- Default/compat profile keeps common apps and attachments working.
189- Attachments remain reachable by service alias where intended.
190- Network groups still work when configured.
191
192### Security behavior to verify
193- `internal` network option is applied when configured.
194- Strict profile applies readonly rootfs/user/caps as designed.
195- `no-new-privileges:true` and cap dropping are preserved.
196- Compat profile behavior is documented and tested.
197
198### Suggested tests
199- Docker adapter config construction tests.
200- Container service tests for network option propagation.
201- Manual smoke: deploy app + postgres attachment in compat profile.
202- Manual smoke: deploy simple read-only app in strict profile.
203
204## Install, Dockerfile, and supply-chain
205
206### Normal behavior to preserve
207- `install.sh` installs the binary on Linux/macOS.
208- GitHub composite action installs Gordon in CI.
209- Dockerfile builds successfully.
210
211### Security behavior to verify
212- Tar extraction only extracts `gordon`.
213- Installed binary must be a regular file, not symlink/directory.
214- Permissions are explicit (`0755`).
215- Checksums/signatures are verified consistently.
216- Gitleaks output is clean or only contains allowlisted examples.
217
218### Suggested tests
219- Shellcheck/manual review for install script.
220- Action script dry-run if practical.
221- Docker build smoke after version alignment.
222- Gitleaks on `git archive HEAD`, not local `.worktrees`.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close