fix(runtime#86): regression gate against token-in-URL in workflows + scripts #166
Closed
agent-dev-b
wants to merge 2 commits from
fix/86-git-askpass-no-token-in-argv into main
pull from: fix/86-git-askpass-no-token-in-argv
merge into: molecule-ai:main
molecule-ai:main
molecule-ai:fix/concierge-mcp-npm-gitea-auth
molecule-ai:feat/openclaw-concierge-mgmt-mcp
molecule-ai:fix/concierge-failclosed-gate-cross-runtime
molecule-ai:feat/base-adapter-system-prompt-ssot
molecule-ai:fix/runtime-model-derived-provider-143
molecule-ai:fix/mcp-contract-legacy-removal-2
molecule-ai:fix/mcp-contract-legacy-removal
molecule-ai:fix/3159-platform-mcp-runtime-agnostic
molecule-ai:fix/3164-platform-mcp-diag-observability
molecule-ai:fix/133-compact-context-and-continue
molecule-ai:fix/131-merge-runtime-version-bumps
molecule-ai:fix/52-propagate-pr-post-retry-backoff
molecule-ai:fix/162-oauth-via-anthropic-auth-token-under-cp-proxy
molecule-ai:fix/3164-layer2-self-heal-observability
molecule-ai:fix/3164-wire-identity-gate-payload
molecule-ai:fix/llm-auth-drop-oauth-on-cp-proxy
molecule-ai:fix/2970-protect-management-mcp-from-user-plugin-eviction
molecule-ai:feat/3082-loaded-mcp-tools-producer
molecule-ai:fix/38-mcp-tool-ssot
molecule-ai:ssot/mcp-plugin-delivery-contract-gate
molecule-ai:fix/87-boot-routes-regression-test
molecule-ai:fix/143-a2a-client-json-guard
molecule-ai:fix/141-load-config-opt-fallback
molecule-ai:fix/118-empty-workspace-config-path
molecule-ai:fix/138-typed-a2a-marker
molecule-ai:fix/consumer-drift-guard-blind-spot
molecule-ai:fix/propagate-dual-pin-templates
molecule-ai:fix/2832-automemory-redaction
molecule-ai:fix/durable-memory-persistence-injection
molecule-ai:fix/surface-agent-error-detail
molecule-ai:fix/2723-heartbeat-dedicated-thread
molecule-ai:feat/ack-first-responsiveness
molecule-ai:fix/drift-ssot-latest-release
molecule-ai:fix/publish-precheck-not-skip-existing
molecule-ai:fix/runtime-propagation-new-branch-source-base
molecule-ai:fix/propagate-branch-base
molecule-ai:fix/publish-skip-existing
molecule-ai:feat/2606-workspace-request-tools
molecule-ai:feat/spec1-bounded-inbox-queue
molecule-ai:fix/tag-only-auto-release
molecule-ai:release/0.3.14
molecule-ai:ci/auto-bump-publish-on-main
molecule-ai:feat/agent-liveness-a1-tool-timeouts
molecule-ai:feat/agent-responsiveness-e2e
molecule-ai:feat/a2a-nonblocking-default-on
molecule-ai:chore/bump-0.3.13
molecule-ai:fix/a2a-queue-not-interrupt
molecule-ai:fix/heartbeat-skip-nonresult-rows
molecule-ai:chore/bump-runtime-0.3.12
molecule-ai:fix/agent-runtime-per-completion-timeout
molecule-ai:fix/2421-heartbeat-carries-agent-card
molecule-ai:fix/1180-lazy-workspace-id-import
molecule-ai:fix/runtime-104-deterministic-git-credential
molecule-ai:fix/a2a-client-lazy-workspace-id
molecule-ai:fix/98-buffer-api-python312
molecule-ai:fix/executor-helpers-non-string-uri
molecule-ai:bump-0.3.10-cross-cloud
molecule-ai:fix/cross-cloud-advertise-injected-url
molecule-ai:harden/contract-tests-runtime
molecule-ai:fix/a2a-2251-outbound-envelope-role
molecule-ai:feat/runtime91-auto-pin-propagation
molecule-ai:release/runtime-v0.3.9
molecule-ai:fix/2200-desktop-coord-1to1
molecule-ai:test/issue-87-boot-routes-real-subprocess
molecule-ai:fix/extract-message-text-protobuf-iterable
molecule-ai:feat/browser-profile-dir-env
molecule-ai:release/runtime-v0.3.7
molecule-ai:fix/runtime-honors-provider-drop-inherited-oauth
molecule-ai:fix/internal-688-boot-register-retry
molecule-ai:fix/dedupe-set-current-task-extract-text
molecule-ai:agent-dev-b/test-card-helpers-and-redactor
molecule-ai:agent-dev-b/test-not-configured-handler
molecule-ai:agent-dev-b/test-rbac-policy
molecule-ai:agent-dev-b/test-transcript-auth-rca-328
molecule-ai:agent-dev-b/test-platform-comm-contract
molecule-ai:fix/runtime-template-pins-check
molecule-ai:fix/stdio-transport-regression-test-option-b
molecule-ai:agent-dev-b/stdio-transport-revive
molecule-ai:fix/ruff-cleanup-e402-f401-f841-e741
molecule-ai:fix-52-missing-retry-backoff
molecule-ai:agent-dev-b/runtime-stdio-tests
molecule-ai:fix-52-cascade-credential-safety
molecule-ai:agent-dev-b/runtime-type-errors
molecule-ai:agent-dev-b/runtime-small-cleanups
molecule-ai:fix/fullscreen-desktop-browser
molecule-ai:fix/xorg-firefox-display
molecule-ai:fix/xvfb-falkon-window
molecule-ai:release/runtime-0.3.3
molecule-ai:fix/xvfb-falkon-browser
molecule-ai:fix/xvfb-chrome-flags
molecule-ai:feat/desktop-control-tools
molecule-ai:fix/ruff-test-only-e401-multi-imports
molecule-ai:chore/maintained-runtime-cascade
molecule-ai:fix/external-upload-push-attachments
molecule-ai:fix/hermes-user-attachments-runtime
molecule-ai:fix-15-pin-shas-runtime-phase2
molecule-ai:fix-52-hardcoded-network-probe
molecule-ai:fix-49-validate-needs-timeouts
molecule-ai:fix/l4-vlm-image-descriptions
molecule-ai:fix/l4-vision-attachments
molecule-ai:fix/attachment-l4-runtime
molecule-ai:fix/credential-helper-file-leak
molecule-ai:chore/gitea-only-ci
molecule-ai:feat/rfc-upload-resolution-mandatory-contract
molecule-ai:fix/publish-cascade-prs
molecule-ai:ssot/base-mcp-tools-contract
molecule-ai:fix/layer2-peer-info-defensive-read
molecule-ai:test/platform-comm-contract-workflow
molecule-ai:fix/durable-delegation-platform-url-ssot
molecule-ai:fix/rbac-policy-ssot
molecule-ai:fix/standalone-mcp-rbac-config-default
molecule-ai:docs/multi-external-workspace-registration
molecule-ai:chore/consumer-drift-secret-preflight
molecule-ai:chore/consumer-runtime-drift-guard
molecule-ai:chore/ci-full-runtime-test-guard
molecule-ai:fix/multi-workspace-platform-url-runtime
molecule-ai:fix/stop-all-bash-subprocess-cancel-propagation
molecule-ai:fix/heartbeat-notify-success-suppress
molecule-ai:chore/runtime-ssot-gitea-publish
molecule-ai:fix/190-self-delegation-regression-tests
molecule-ai:fix/378-non-blocking-a2a-handler
molecule-ai:feat/296-per-workspace-platform-url
molecule-ai:migration/standalone-ssot
molecule-ai:fix/pin-python-multipart-for-chat-upload
molecule-ai:feat/agent-card-update-and-runtime-identity-tools
molecule-ai:runtime/fix-a2a-mcp-module-invocation
molecule-ai:runtime/idle-loop-skip-pending-delegations
molecule-ai:runtime/idle-loop-check-pending-messages
molecule-ai:runtime/offsec-003-delegation-only
molecule-ai:runtime/platform-url-host-docker-internal
molecule-ai:runtime/fix-offsec-003-read-delegation-results
molecule-ai:sre/OFFSEC-003-mcp-prompt-injection-guard
molecule-ai:fix/a2a-mcp-server-review-fixes
molecule-ai:runtime/http-mcp-review-fixes
molecule-ai:runtime/review-pr5-http-mcp-fixes
molecule-ai:fix/hermes-mcp-platform-tools
molecule-ai:fix/a2a-sdk-constraint-to-1x
molecule-ai:fix/post-suspension-github-urls
molecule-ai:fix/lowercase-org-slug
molecule-ai:docs/readme-pypi-vs-mirror-clarification
No Reviewers
Milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
agent-dev-a
agent-dev-b
agent-pm
agent-researcher
agent-reviewer
agent-reviewer-1
agent-reviewer-cr2
app-fe (Molecule AI · app-fe)
app-lead (Molecule AI · app-lead)
app-qa (Molecule AI · app-qa)
claude-ceo-assistant
claude-ci-reader
core-be (Molecule AI · core-be)
core-devops (Molecule AI · core-devops)
core-fe (Molecule AI · core-fe)
core-lead (Molecule AI · core-lead)
core-offsec (Molecule AI · core-offsec)
core-qa (Molecule AI · core-qa)
core-security (Molecule AI · core-security)
core-uiux (Molecule AI · core-uiux)
cp-be (Molecule AI · cp-be)
cp-lead (Molecule AI · cp-lead)
cp-qa (Molecule AI · cp-qa)
cp-security (Molecule AI · cp-security)
cui (Zhanlin Cui)
dev-lead (Molecule AI · dev-lead)
devops-engineer
documentation-specialist (Molecule AI · documentation-specialist)
fullstack-engineer (Molecule AI · fullstack-engineer)
godwin
hongming
hongming-ceo-delegated
hongming-codex-laptop
hongming-kimi-laptop
hongming-pc2
hongming-personal
infra-lead (Molecule AI · infra-lead)
infra-runtime-be (Molecule AI · infra-runtime-be)
infra-sre (Molecule AI · infra-sre)
integration-tester (Molecule AI · integration-tester)
molecule-code-reviewer
molecule-runtime-release-bot (Molecule Runtime Release Bot)
plugin-dev (Molecule AI · plugin-dev)
pm
publish-runtime-bot
pypi-publisher (Molecule AI PyPI Publisher (RFC#596))
release-manager (Molecule AI · release-manager)
sdk-dev (Molecule AI · sdk-dev)
sdk-lead (Molecule AI · sdk-lead)
sop-tier-bot (SOP Tier-Check Bot)
technical-writer (Molecule AI · technical-writer)
triage-operator (Molecule AI · triage-operator)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: molecule-ai/molecule-ai-workspace-runtime#166
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "fix/86-git-askpass-no-token-in-argv"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Closes runtime#86 (last gap): a regression gate that fails the build if
x-access-token:${TOKEN}is re-introduced in any workflow or script. Closes the same-class leak shape as runtime#161/#162 (auth/sibling security work).Why this is the last piece
Kimi's prior commit on this branch (
061716f, 2026-06-07) converted the Python audit scripts (check_consumer_runtime_drift.py,check_platform_comm_contract.py) to use GIT_ASKPASS so the token never lands in subprocess argv or the git remote URL.Meanwhile on
main, the actual publish-runtime cascade had already been replaced (commits28cbf9b,7154e15) with a Gitea contents+pulls API approach — nogit clone, no on-disk remote URL with a token. So the practical leak surface is closed. The missing piece was the regression guard so the next PR that re-introduces the pattern goes red in CI rather than red in production.PM dispatch explicitly called this out: "Security-sensitive auth work like #162 is great — if you spot a sibling auth-leak issue to #161/#162, flag it." runtime#86 is the same family.
What the gate scans
.gitea/workflows/*.yml— the CI surfacescripts/*.py— the audit-script surface (clone helpers invoked by the workflows)scripts/*.sh— shell helpers (none shipped; covered for symmetry)What the gate matches (forbidden)
x-access-token:followed by a token-looking value:${VAR}— bash env-var interpolation${{ ... }}— GitHub Actions expression{var}— Python f-stringWhat the gate does NOT match (allowed)
echo "x-access-token"username response — the documented safe shape (token rides the password prompt, not the URL). Pinned bytest_askpass_username_response_is_the_only_allowed_occurrenceso a refactor of the askpass helper doesn't silently break the gate.Tests (4 new)
test_scan_targets_exist— defence-in-depth; vacuous-pass guard (the gate must scan something).test_no_workflow_or_script_embeds_token_in_clone_url— the main check; reports(file, line-no, line)for every offender.test_askpass_username_response_is_the_only_allowed_occurrence— pins the documented exception.test_leak_regex_does_not_match_comment_lines— regression guard for the gate itself.Positive control (manual, reproducible)
Inject into
.gitea/workflows/publish-runtime.yml:Re-run the gate → red:
Revert the injection → green. Tested locally before opening this PR.
Test counts
tests/test_llm_auth.pytests/test_consumer_runtime_drift_guard.pytests/test_platform_comm_contract_guard.pytests/test_workflow_no_token_in_url.pyAll 51 pass on the branch HEAD (
21d9ce0).Scope
Single-purpose: closes runtime#86. ~235 lines of test code; zero production-code changes on this commit (Kimi's
061716falready covered the script surface). Behaviour-preserving; pure additive CI gate.Independence from the red #3164 deployment surface
Pure workflow / scripts / CI gate. No concierge / MCP / heartbeat / identity-gate / operator-deployment surface touched. Safe to merge on the runtime-lane (CI-only gate; doesn't need the operator #3164 redeploy).
Gate
unit-testsjob +secret-scanjob (this gate adds to the test surface)Closes the remaining acceptance-criteria gap from runtime#86: a regression test that fails the build if the x-access-token-in-clone-URL pattern is re-introduced in .gitea/workflows/*.yml or scripts/*.{py,sh}. Why this is the last piece -------------------------- Kimi's prior commit (061716f) on this branch converted the Python audit scripts to use GIT_ASKPASS so the token never lands in subprocess argv or the git remote URL. The publish-runtime.yml cascade had ALREADY been replaced (commits28cbf9b,7154e15) with a Gitea contents+pulls API approach — no git clone, no on-disk remote URL with a token. So the practical leak surface is closed; the missing piece is the regression guard so the next PR that re-introduces the pattern goes red in CI rather than red in production. What the gate scans ------------------- * .gitea/workflows/*.yml — the CI surface * scripts/*.py — the audit-script surface (clone helpers used by CI) * scripts/*.sh — shell helpers (none shipped; covered for symmetry) What the gate matches --------------------- x-access-token: followed by a token-looking value: 1. bash ${VAR} 2. GitHub Actions ${{ ... }} 3. Python f-string {var} 4. a quoted token literal (>=8 chars) What the gate does NOT match ---------------------------- * The GIT_ASKPASS helper's 'echo "x-access-token"' username response (the token rides the password prompt, not the URL — the documented safe shape). * Comment lines (the prior fix's commit message + this test file reference the pattern as documentation; the comment-line skip is applied at the scan layer). Tests ----- * test_scan_targets_exist — defence-in-depth, the gate scans something (vacuous-pass guard). * test_no_workflow_or_script_embeds_token_in_clone_url — the main check. * test_askpass_username_response_is_the_only_allowed_occurrence — pins the documented exception so a refactor of the askpass helper doesn't silently break the gate. * test_leak_regex_does_not_match_comment_lines — regression guard for the gate itself (verifies the comment-skip is wired up). Positive control (manual): injecting - run: git clone "https://x-access-token:${SECRET}@github.com/x/y" into .gitea/workflows/publish-runtime.yml and re-running the test produces a clear, file:line-cited failure: Forbidden token-in-URL pattern detected (runtime#86 regression). ... Offenders: .gitea/workflows/publish-runtime.yml:161: - run: git clone ... Existing tests still pass: tests/test_llm_auth.py — 35/35 tests/test_consumer_runtime_drift_guard.py — 6/6 tests/test_platform_comm_contract_guard.py — 6/6 tests/test_workflow_no_token_in_url.py — 4/4 Total 51/51. Closes: runtime#86 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Pull request closed