| .. | ||
| evidence | ||
| postimages | ||
| preimages | ||
| tests | ||
| chart-private-input.patch | ||
| forgejo-private-input.patch | ||
| README.md | ||
| shared-db-confidentiality.patch | ||
| SQL-CONFIDENTIALITY.md | ||
Forgejo private client-secret input: separate source revision
This packet implements --secret-file in the actual Forgejo 11.0.3 add/update
OAuth handlers and patches the actual Gitea chart 12.5.0. Apply the unchanged
reviewed seven-path any-of patch first, then this incremental Forgejo patch.
The original candidate and completed release-build packets remain unchanged.
No canonical owner implementation, case/type, authority, image or deployment is
changed. The new backend executable is test evidence, not an admitted image.
The existing three-group exact any-of gate and mandatory current-UserInfo guard
remain in the reviewed implementation. Six reviewed non-CLI source paths retain
exact hashes. Actual cmd/oauth2 package tests exercise them again. The exact shared database
confidentiality dependency is documented in SQL-CONFIDENTIALITY.md;
apply it once when composing source candidates. Both handlers refuse raw SQL
logging, mark queries for hook/trace redaction, and private-file persistence
failures return fixed errors. Update without
secret flags preserves the stored secret; selecting a private input completes
its checks before DB initialization or source mutation. Explicit legacy
--secret behavior is preserved. Both flags together, including an empty legacy
flag, refuse. The file value never enters the CLI context, argv or environment.
On Linux the reader walks absolute, normalized paths with descriptor-relative
non-following opens, rejects writable-by-group/other parents and foreign-owned
parents, and opens the leaf nonblocking so FIFO input cannot hang. It requires a
single-link regular file, root/euid ownership, no write/execute/special/other-read
bits, an admitted process group for group-readable files, and an actual read-only
mount. It bounds the read at 65 bytes and compares file identity/size/ownership/
mode/mtime/ctime and the named leaf after reading. Read-induced atime is allowed.
Every file-input failure has the same fixed error without path or value. Other
platforms fail closed. The accepted format matches the actual mint implementation:
48 random bytes encoded by secrets.token_urlsafe, exactly 64 ASCII base64url
characters with no padding or newline. Values are preserved exactly; no trimming
occurs. The transient read buffer is cleared; the existing DB/provider string
custody and process memory remain the existing software contract.
The chart helper suppresses automatic --secret when secretFile is present.
It refuses secret, existingSecret, indexed secret env collisions, multiple
private entries, a different path, conflicting extra mounts/volume and a different
fsGroup. Its bounded private route emits the fixed path and mounts existing
forgejo-netkingdom-oidc-client key CLIENT_SECRET read-only by file subPath
into configure-gitea only, with mode 0440 and pod fsGroup 1000. No alias key,
new secret read/ACL, value-bearing env or value-bearing agent command is added.
Legacy sources retain their existing automatic argument behavior. Exact public
release values are deliberately not emitted by these synthetic controls.
Linux Kubernetes Secret volumes normally retain root UID. The fsGroup ownership pass changes GID and adds read permissions, so root:1000 mode 0440 is expected; requiring euid ownership would incorrectly refuse this case. The retained public Kubernetes ownership implementation and Secret volume implementation show those details. File subPath bind mounting avoids the projected symlink leaf; Secret subPath mounts do not receive automatic updates. An owner-controlled restart/refresh is required on rotation. These public source findings are not observations of the estate's running kubelet or pod.
DAC and a read-only mount cannot identify a Kubernetes namespace, Secret object, operation session, or authorized reader set. The reader intentionally makes no such admission claim. Actual runtime admission must bind the exact owner workload, image, namespace, mount/parent ownership, UID/GID/mode, reader set, rotation and current authenticated operation. Arbitrary privileged code or a malicious workload owner remains outside this input reader's protection. T34 persistence/readback/CAS, durable journal, writer exclusion, operation/inverse sessions and the application-state inverse remain separate owner work. A Helm rollback alone does not reverse persisted source state.
The retained checks compile the actual complete backend and execute actual binary CLI subprocesses against a synthetic SQLite database. They cover add, replacement, omission, preservation of unrelated configuration and guarded three-group fields, bad-path/input refusals and conflicts without DB changes, and absence of values in argv/env/stdout/stderr. Actual Linux descriptor tests exercise opened-inode/name replacement, while metadata controls include root:fsGroup 0440 and prohibited modes. Actual Helm rendering covers both command forms, the Secret/mount references, legacy behavior, and refusal without leaking a conflicting synthetic marker. Guard tests use in-memory HTTP transports. The CLI guarded-update persistence control uses an inactive source to avoid discovery; it is not a browser login or an active OIDC registration proof.
Final decisive build/test profiles use bwrap PID and network isolation, public-only source/cache mounts, an empty test HOME and a closed environment. No host HOME/config, credentials, cluster, OpenBao, registry publication, model call or live secret is used. No full frontend/container/image rebuild was launched. Earlier profiles without PID isolation, initial fixture and sandbox harness failures, a reproduced synthetic SQL leak before correction, and the earlier-revision replay failure are retained, as is the initial chart metadata mismatch and its exact published-metadata reconstruction; none is counted as a successful runtime trial.
Run a fresh reconstruction and all actual checks with the retained public cache:
python3 tests/replay_offline.py --public-cache /tmp/forgejo-independent-r1
This creates fresh /tmp source/work/evidence, applies both exact patches, and
builds only a backend test executable. It needs bwrap, patch, Python/PyYAML, the
existing Helm executable and the already retained public Go/module cache. The
packet includes only changed source pre/postimages, small public provenance,
patches and tests; no vendored full source, binary or image is included.