Skip to content

fix(compose): retain mounted secret file authority - #281

Draft
seonghobae wants to merge 7 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/compose-secret-file-authority-b84f0c9
Draft

fix(compose): retain mounted secret file authority#281
seonghobae wants to merge 7 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/compose-secret-file-authority-b84f0c9

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

ACTIVE Draft — retained mounted-secret descriptor authority

Protected main@b84f0c94154043a3473939c01bb6471de5a129ae remains unchanged. This source lane is fix/compose-secret-file-authority-b84f0c9, an explicit child of dependency-root #233@5951b7a4d779903b8924abaef2a387cae50b7f54. Exact current head is c00111e54f21c4cf90036ee66072d5fafaed3ef6, Draft and mechanically mergeable. No source or documentation was written directly to protected main.

Defects proven test-first

Final-component substitution

The earlier standalone Compose bootstrap opened an explicit mounted password-file path through ordinary pathname resolution. A final symlink could therefore redirect password authority away from the mounted-secret object selected by the operator.

The branch retains one package-owned descriptor opened with O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK, rejects platforms that cannot provide the no-follow boundary instead of silently downgrading, proves a regular-file inode before reading, bounds the read, and closes retained authority explicitly. FIFO/non-regular objects, descriptor metadata failures, and close failures remain fixed/content-free failures.

In-place mutation after initial inspection

Test-first commit e0ec0b08bf9ebffbbf5310d86e549a47a0fd1f36 adds a deterministic regression that changes the same retained secret object after the initial descriptor stat and requires fail-closed ConfigError rather than accepting modified bytes.

Current GREEN c00111e54f21c4cf90036ee66072d5fafaed3ef6 snapshots retained regular-file metadata before the bounded read and re-reads descriptor metadata afterward. It rejects observed mode, size, link-count, owner/group, device/inode, mtime, or ctime change through the existing fixed unavailable category. Both observations and the read use the same retained descriptor, so pathname substitution cannot regain authority; mutation after the final metadata observation cannot change the already captured password bytes.

The repair intentionally does not add host-owner/mode assumptions that would reject ordinary container secret mounts, claim immutability against host-root compromise, or expose secret text in argv/logs/telemetry/errors.

Exact current-head validation

The previous body’s queued/pending description is stale. Fresh commit-scoped inventory for unchanged exact c00111e54f21c4cf90036ee66072d5fafaed3ef6 now shows:

  • CI 32372722989: success;
  • Release Acceptance 32372723081: success;
  • Security Scan: absent on this exact head; and
  • SAST Semgrep: absent on this exact head.

Fresh formal reviews and inline review threads are empty. Exact-head CI/release success does not transfer predecessor security evidence; absent Security/SAST and absent approval remain non-passing.

Writer / integration boundary

Fresh lifecycle adjudication in #316 proves retained agent/compose-loopback-publishing@4debfc68655e300a6c393b0cbd3c251daf4faf03 is SUPERSEDED_RETAINED, not current Compose implementation/writer authority: its owning Draft #91 is closed unmerged and explicitly superseded by merged #138, whose merge commit b7f8a48d4745ebd1b429027168c3d2f776c6a4a7 is independently proven in current protected-main ancestry. Preserve that historical ref for provenance; do not delete, rewrite, or transfer its old evidence. fix/compose-bootstrap-runpy-warning-b84f0c9 remains a separate warning-test slice. This correction does not declare the mounted-secret source/test surface globally writer-free: before any future source mutation, freshly inventory all then-current PR/no-PR refs and exact changed paths, and freeze this lane if another actor moves or overlaps it.

Keep #281 Draft behind #233. After #233 reaches protected main through then-live governance, reconcile/retarget this branch to the resulting exact protected base and reacquire one unchanged exact-final-head proof for supported Python including 3.14, exact 100% owned production statement/branch coverage, public docstrings, package/container, Security Scan, SAST, SBOM/provenance/release acceptance, zero valid findings/threads, and any qualifying independent current-last-push approval required by live policy. Do not copy or bypass read-only central .github control-plane logic.

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f62303b0-9e20-4bd6-bccf-30d8c1566227

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

Exact current head e6cdad40273fa48f1075d2b443d3904ffbe31c7a closes final-symlink and non-regular/FIFO authority, but one fail-closed normalization gap remains in the new open boundary. os.open(password_file, secure_flags) raises ValueError rather than OSError for an embedded-NUL path; current source catches only OSError, so _load_database_password(Path("private-secret\x00suffix")) leaks a raw implementation exception instead of the fixed content-free ConfigError(_SECRET_UNAVAILABLE) boundary. This is independently reproducible on the supported Python runtime. Please add a focused RED for an embedded-NUL Path and include ValueError in the narrow open-failure normalization without broadening the catch around process-control paths. The branch moved during this invocation, so I am not mutating the source lane.

@seonghobae
seonghobae changed the base branch from main to fix/recovery-evidence-weakref-coverage-b84f0c9 August 20, 2026 06:56
@opencode-agent opencode-agent Bot added area: auth Authentication, authorization, identity, or tenant isolation area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth Authentication, authorization, identity, or tenant isolation area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant