Conversation
One squashed commit carrying the full PR GenAI-Security-Project#22 branch, rebuilt on current main (DCO: all history signed; branch is a direct child of main). Adapters (each: acs_adapter, wire.py, mapping.md, README, tests): - Claude Code: hook-to-steps translation with explicit turn tracking (turnStart/turnEnd, per-session state), native allow/deny/ask, modify via merged updatedInput, defer substituted to deny + audit. SubagentStop is deliberately unmapped: steps/subagentStop requires final_chain_hash, which a chain-less framework cannot honestly produce; a separate schema PR proposes making it optional. ADAPTER_VERSION 0.1.3. - Cursor: documented-field payload builders (docs.cursor.com, 2026-08-22), turn tracking, beforeSubmitPrompt exit-2 blocking, failure_type-to-exit_status mapping, fail-closed contradictory modifications per §6.3. - NAT: pre/post-invoke middleware with negotiated timeouts, durable audit sink, redaction-or-deny output gate. Shared infrastructure: - acs_common: RFC 8785 (JCS) + HKDF per-session HMAC signing (§10), handshake with signed ServerHello binding and negative cache, total decision normalization, §6.3 composition-violation check. - example_guardian: signed error envelopes, capped regex scanning, durable file-locked replay state, subagent gate no weaker than the generic tool gate. Binds --port 0 and announces the assigned port on stdout so test spawns own their port by construction. - Conformance + emission suites (230 checks) driving both CLI adapters and the Guardian; NAT covered by its own suite (35). Guardian refusal handling is deliberately stricter than v0.1 spec text (always fail closed); tracked as spec issue GenAI-Security-Project#32. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Bar Kaduri <bar@capsule.security>
Translate tool calls through the shared ACS signing and handshake helpers. Apply allow, deny, and supported parameter modifications using Codex's native hook output; deny unsupported ASK/DEFER and unusable modifications. Include configuration, mapping, emission tests, CLI enforcement verification, and conformance-runner/CI registration. Advertise only the implemented method and transport, with no ACS-Core profile claim. Refs GenAI-Security-Project#89; first tool-call slice. Based on GenAI-Security-Project#22. Signed-off-by: Lrd0036 <lrd0036@auburn.edu>
|
Thanks for the Codex slice. I found one interoperability issue in The current code reads server_hello = (response.get("result") or {}).get("payload")ACS v0.1 returns server_hello = response.get("result")The TypeScript Guardian uses this standard handshake shape too. Could this be corrected and covered by an interoperability test against the TypeScript Guardian? |
Read ServerHello directly from the JSON-RPC result on fresh and cached handshakes. Update both Python response producers and the affected fixtures while retaining response binding, signature verification, and whole-envelope cache validation. Add focused regressions for direct-result negotiation, cache reuse, tampering, unsigned responses, request binding, legacy wrappers, schema conformance, and the shipped Python Guardian round trip. Signed-off-by: Lrd0036 <lrd0036@auburn.edu>
|
Yes! Thanks for catching this. d077978 fixes both fresh and cached reads, both Python response producers, and the affected fixtures. It adds 13 regressions while preserving signature verification, request binding, and whole-envelope caching. The repaired local adapter gate passed 304 tests with three expected live-product skips; the PR description now separates those results from the original commit's results. The TypeScript portion is still open. I ran the TypeScript Guardian, and its direct ServerHello validates against the handshake schema... but the response is unsigned. Its README documents the authentication/signing bit. With a nonempty key and signature verification enabled, Codex rejects that peer. This is wire-shape compatibility and rejection coverage, not a successful signed integration, and the diagnostic is not committed in this repair. Would a committed test that launches the TypeScript Guardian, validates its direct-result shape, and asserts rejection by the signed Python/Codex path meet the coverage expected for this repair, with positive signed end-to-end interoperability tracked separately pending TypeScript signing support? The new head's Deploy Pages and adapter-tests runs both show Follow-up: I’ve committed the TypeScript coverage in b2d4b49. It launches the actual Guardian, validates the direct ServerHello shape, and checks that the shared helper and default-deny Codex adapter reject its unsigned response. Signature verification remains enabled. |
Launch the shipped TypeScript Guardian and validate its direct ServerHello against the canonical schema. Exercise the signed shared helper and Codex adapter against its unsigned reply, asserting rejection without a cached handshake or a tool request. Run this coverage in a dedicated Bun/Python CI job alongside the signed Python controls. Document the distinction between wire-shape compatibility and successful authenticated interoperability. Signed-off-by: Lrd0036 <lrd0036@auburn.edu>
|
@Lrd0036 you had the ServerHello fix up the same day @President found it, with 13 regression tests behind it, and I've got one housekeeping ask. Could you add |
|
Done, thanks! |
|
Oops. Both authoritative and conformance failures come from the same citation guard in adapters/test_acs_core_conformance.py: an upstream diagram moved the specification’s line numbers.
|
Anchor the Core citation guard to its section and ordered requirement names so upstream diagrams do not break conformance checks. Preserve behavioral assertions and cover moved, missing, and renamed citations. Disable checkout credential persistence in the adapter jobs and correct the setup-bun version comment to match its existing pin. Signed-off-by: Lrd0036 <lrd0036@auburn.edu>
|
Fixed & pushed 49f5232. Citation guard now follows ACS-core reqs. instead of the fixed line numbers. Also addressed that workflow cleanup flagged by #179. |
…179) CodeQL default setup was turned on for this repository on 2026-09-21 and covers the Actions language. This adds zizmor, which the [OWASP GitHub Actions Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/GitHub_Actions_Security_Cheat_Sheet.html) recommends beside CodeQL for defense in depth. zizmor reads each workflow's logic and checks what CodeQL does not: hash pins no tag points to, version comments that disagree with their pin, App tokens broader than the job needs, and credentials a checkout leaves in `.git/config`. Run against `integration` before this change with online audits on, zizmor 1.30.1 reported 15 findings. This clears 13. The other two are `github-app` findings on `board-reconcile.yml`, whose App token takes the installation's full grant instead of naming its repository and permissions. Token scopes are not changing right now, so those two stay open in code scanning, where they record the deferred decision instead of disappearing behind a suppression. - **`pr-intake.yml`, 1 high.** zizmor flags every `pull_request_target`. This one checks out no code and reads the pull request body as data through an environment variable, which the workflow's header already explains. It carries an inline `zizmor: ignore` that points at that explanation. - **Eleven checkouts across nine workflows, 11 low.** Each left the job's token in `.git/config`. None of those jobs pushes with git. They call `gh` with `GH_TOKEN` or touch no network at all, and `sync_version.yml` hands its push to `create-pull-request`, which configures its own token. All eleven now set `persist-credentials: false`. The checkout in `validate-owasp-metadata.yaml` also gains the `# v7.0.1` comment every other pin carries. - **`reference-implementation.yml`, 1 medium.** The setup-bun pin `735343b` is v2.0.2, and its comment said v2.0.1. Only the comment changes. Dependabot's #83 already treats it as 2.0.2. The new workflow runs zizmor from a `zizmor` dependency group in `uv.lock`, pinned with hashes. No new action enters the Actions allowlist, and Dependabot's uv ecosystem moves zizmor under the existing 7-day cooldown. The group is not a default group, so `uv sync --locked` in the deploy and test jobs never installs it. A default sync against this lockfile would uninstall it. It runs on pull requests and pushes that touch `.github/`, an action definition, `pyproject.toml`, or `uv.lock`, and weekly, because the online audits compare pins against advisories published after the pin. Findings upload as SARIF under the category `zizmor`, and the job stays green on findings so code scanning tracks them and a ruleset can gate on them later. A tool or upload failure still fails the job. A pull request from a fork cannot upload with its read-only token, so it gets annotations instead. `upload-sarif` is pinned at v4.38.0 because v4.38.1 was three days old, inside the cooldown this repository applies to its dependencies. Open pull requests #162 and #169 add workflows that zizmor will flag once they land, for unset `persist-credentials` and the same `# v2.0.1` setup-bun comment. Verified locally: zizmor 1.30.1 with online audits reports only the two deferred `github-app` findings, with 1 ignored and 26 low-confidence findings suppressed by the default persona. The workflow's own command produces valid SARIF 2.1.0. `actionlint` is clean. `uv lock --check` passes under uv 0.9.9, the version CI pins, and the lockfile diff adds only zizmor. `uv run pytest` gives 278 passed, 1 skipped. Signed-off-by: Rock Lambros <rock@rockcyber.com>
What changed
Add a signed Codex
PreToolUseadapter: tool calls becomesteps/toolCallRequest, and Guardian decisions become native allow, deny, or supported parameter overrides. It reuses #22's Python signing, handshake, binding, and decision helpers, with configuration, mapping, CI registration, and runnable verification.Ready for review — depends on #22. This branch is #22 at
7174a033c15f69ee58caaa5eb0a19279592171c7plus the original Codex commit3d4bdb3, ServerHello repaird077978, and TypeScript coverageb2d4b49described below. The full PR diff temporarily includes the inherited adapter stack. For the original Codex slice, review the Codex commit: 15 files, 1,063 insertions, 9 deletions. The optional shared-transport cleanup is excluded.Before merging, I will rebase the Codex slice and any still-needed repair changes onto
integrationafter #22 lands, reconcile upstream changes, and rerun the checks and live enforcement on that final base. The original results below remain tied to3d4bdb3; the review follow-up records separate verification of the repaired tree.Which issue does this implement
Closes #170
Refs #89 (
status:accepted,help wanted). This implements the tool-call slice and leaves the issue open for lifecycle/result coverage.Base branch
integration, because this adds an adapter, tests, and CI.This PR exposes the completed slice while its dependency remains open; it is not ready to merge until #22 lands and the final rebase is complete.
Type of change
I tested this — original commit (historical)
Rerun against Codex-only commit
3d4bdb3e84665e6db13835bc075ee8ec876bc14b:integrationbase (pending Add adapters/ with Claude Code, Cursor, and NAT reference implementations #22).uv run --locked pytest -v: 205 passed, one case-insensitive-filesystem skip.uv run --locked mkdocs build --strict: passed.python run_conformance.py claude cursor nat codex: 291 passed, no failures, three expected live Claude/Cursor skips. All 35 NAT tests and all 26 Codex tests ran.The local model endpoint supplies a fixed tool call; these runs test execution enforcement, not model inference. Live runs used explicit inline hook configuration and the one-shot hook-trust bypass. Project-file hook discovery and interactive trust remain unverified. An isolated project-file probe sent no Guardian requests and was not counted as a pass. The shipped teaching policy does not generate MODIFY, so that path has fixture coverage only. MCP/patch translation has subprocess coverage, not live host coverage.
Review follow-up —
d077978Repair commit
d07797805945801e443ab04eaf3a1f8c5c332ff8reads ServerHello directly fromresultfor fresh and cached handshakes, corrects both Python producers, migrates affected fixtures, and adds 13 regressions. Request-ID binding, signature verification, and whole-envelope caching remain in place. Cached legacy wrappers trigger renegotiation.Separate local verification on the repaired working tree, before committing:
The local security assessment reviewed an uncommitted snapshot. Reconstructing the saved repair on
3d4bdb3reproduces its snapshot SHA-256a126300c22a821a33c5b84c29b7b4b37ec7cf2f9c624879a609da69db67bc9e7and the published commit's complete Git tree95757e340f91579273287a33e582997d5c5f9e3e. No source changed between that snapshot and publication; the local commit amendment changed only its message. These are pre-commit local results linked by identical source content, not post-push CI results.TypeScript diagnostic at
d077978(historical). A separate local probe against the actual TypeScript Guardian validated the direct ServerHello shape and observed an unsigned response; configured-key Codex refused it. Its documented endpoint lacks authentication and request signing. This proves shape compatibility and unsigned-peer rejection, not successful authenticated integration. That probe is not committed coverage ind077978. Theb2d4b49follow-up below now commits that coverage. Positive signed interoperability remains pending TypeScript signing support; signature verification stays enabled.Public CI for
d077978: Deploy Pages and adapter-tests both reportaction_required, with zero jobs reported as of 2026-09-20. They establish neither passing validation nor test failures. Maintainer action and completed checks are still pending.TypeScript coverage follow-up —
b2d4b49Commit
b2d4b49092861bf7cee7cddff83572e6f8e5d395adds three tests against the shipped TypeScript Guardian process, a dedicated CI job, and reproduction instructions. It validates the direct ServerHello against the canonical schema, verifies that the configured-key shared helper refuses the unsigned response without caching it, and verifies that default-deny Codex refuses it before sending a tool request. The job also runs the signed Python controls. Missing Bun or workspace dependencies fail the job rather than skip coverage.Local verification on the source tree published in this commit:
An initial adapter run found the locally installed Claude CLI but failed its two live tests because it was not logged in. The headless rerun excluded that optional CLI from PATH and reported the expected skips. Claude live enforcement is not verified here.
This commit changes only tests, CI, and documentation. The prior security snapshot remains evidence for
d077978; it does not cover this later commit. These tests establish wire-shape compatibility and unsigned-peer rejection, not successful signed TypeScript interoperability. The Codex test runs the production adapter subprocess, not the Codex CLI.Public CI for
b2d4b49: adapter-tests and Deploy Pages reportaction_required. Public validation is still pending; these are local results.Checklist
git commit -s.Security and scope
Missing signing configuration, invalid or misbound decisions, and unsupported modifications deny. ASK/DEFER become audited denial because this slice has no supported approval/resumption path. Temporary Guardian failures follow the configured posture; the example sets default-deny.
The adapter advertises one method, HTTP, and no ACS-Core profile. Results, lifecycle events, hosted tools, continued process input, and hook-disabled/untrusted paths remain outside coverage. No specification or policy-engine changes are included in the Codex commit.