Skip to content

fix(ai-safety): prompt injection boundary, hardened model delegate, audit regression fixtures - #44

Merged
2233admin merged 1 commit into
mainfrom
fix/ai-safety-hardening
Jul 27, 2026
Merged

fix(ai-safety): prompt injection boundary, hardened model delegate, audit regression fixtures#44
2233admin merged 1 commit into
mainfrom
fix/ai-safety-hardening

Conversation

@2233admin

Copy link
Copy Markdown
Owner

Summary

Addresses ai-safety-002/004/005/006 from #34 (ai-safety-003 is handled by a separate parallel PR).

  • ai-safety-002 (high): department prompts gave the LLM auditor no instruction/data boundary between the target repo's content and its own operating instructions. Combined with the kernel accepting a self-reported coverage: high as sufficient for a clean 10.0/zero-findings score, a target repo could plant a prompt-injection instruction telling the auditor to report clean. Adds an explicit "Untrusted content boundary" section to all three department prompts (ai-safety.md, security.md, supply-chain.md) and a shared "Untrusted Content Boundary" section to docs/audit-report.md so future departments inherit it.
  • ai-safety-004 (low): HTTP failure classification derived retry-eligibility from a regex over the raw response body even when the numeric status code was already authoritative, so a 500 whose body happened to mention "quota" was misclassified as transient provider_quota. Adds Get-HttpFailureCategory, which classifies purely from the status code (429/401/403/404/503, else local_tool_error) on the HTTP path. The existing regex-over-body Get-FailureCategory now only serves the local-process exit-code path, which has no status code to consult.
  • ai-safety-005 (low): local-process model output was read via ReadToEndAsync with no byte budget, so a runaway/looping model stream could be buffered in full (up to the full timeout, up to an hour) before the artifact-publish size ceiling ever applied. Adds Read-BoundedProcessOutput, which reads stdout in bounded chunks and stops/kills the process once a 4MB cap is exceeded, reporting adapter_protocol_error. Also adds an explicit output-token bound (mirroring the existing anthropic body's max_tokens) to the ollama (num_predict) and openai (max_tokens) request bodies, which previously carried none.
  • ai-safety-006 (info): no adversarial fixture corpus existed for the audit validate pipeline. Adds three fixtures under crates/code-intel-cli/tests/fixtures/audit/ — a nonexistent evidence path, a reversed line range, and a report that fabricates "high" coverage for departments it never assessed — plus three cli_tests.rs cases asserting code-intel audit --operation validate rejects each one.

Scope notes

  • Per the parallel-work constraint, this PR does not touch any .github/workflows/*.yml, dag_run.rs, or execution_kernel.rs.
  • Invoke-ModelChannelDelegate.ps1 is a legacy PowerShell compatibility surface per AGENTS.md; edits here are the explicit "critical fixes" carve-out — no new PowerShell product surface was added, and no unrelated refactoring.

Test plan

  • cargo fmt -p code-intel -- --check passes
  • cargo build -p code-intel passes
  • cargo test -p code-intel passes (761+ tests across the audit_report surface, full suite green on a clean rerun — one runtime_ci_evidence.rs test flaked once with a transient Windows "Access Denied" on a freshly created temp dir, unrelated to any file in this diff; reran clean 3x in isolation and clean on a full-suite rerun)
  • The three new cli_tests.rs cases pass with the exact expected rejection messages (evidence-grounding failure, reversed-range failure, not_assessed/coverage mismatch)
  • pwsh -NoProfile -Command "$null = [scriptblock]::Create((Get-Content -Raw 'Invoke-ModelChannelDelegate.ps1'))" does not throw
  • Existing tests/test-model-channel-delegate.ps1 suite passes unchanged
  • Empirically verified the new byte budget: a fake child process producing ~12.5MB of stdout was truncated in 625ms (not the full 30s timeout), classified adapter_protocol_error

… add audit regression fixtures

Fixes a batch of findings from the code-intel-pipeline ai-safety self-audit
(issue #34):

- ai-safety-002 (high): department prompts gave the LLM auditor no
  instruction/data boundary, so content read from the target repo (AGENTS.md,
  CLAUDE.md, README, code comments) could be mistaken for instructions.
  Combined with the kernel accepting a self-reported "coverage: high" as
  sufficient for a clean 10.0/zero-findings score, a target repo could plant
  a prompt-injection instruction telling the auditor to report clean. Adds an
  explicit "Untrusted content boundary" section to all three department
  prompts (ai-safety.md, security.md, supply-chain.md) and a shared
  "Untrusted Content Boundary" section to docs/audit-report.md so future
  departments inherit it.

- ai-safety-004 (low): failure classification on the HTTP path derived
  retry-eligibility from a regex over the raw response body even when the
  numeric status code was already authoritative, so a 500 whose body
  mentioned "quota" got misclassified as transient provider_quota. Adds
  Get-HttpFailureCategory to classify from the status code alone
  (429/401/403/404/503, else local_tool_error) on the HTTP path; the
  regex-over-body Get-FailureCategory now only serves the local-process
  exit-code path, which has no status code to consult.

- ai-safety-005 (low): local-process model output was read via
  ReadToEndAsync with no byte budget, so a runaway/looping model stream
  could be buffered in full (up to the full timeout) before the artifact
  publish size ceiling ever applied. Adds Read-BoundedProcessOutput, which
  reads stdout in bounded chunks and stops/kills the process once a 4MB cap
  is exceeded, reporting adapter_protocol_error. Also adds an explicit
  output-token bound (mirroring anthropic's existing max_tokens) to the
  ollama (num_predict) and openai (max_tokens) request bodies, which
  previously carried none.

- ai-safety-006 (info): no adversarial fixture corpus existed for the audit
  validate pipeline. Adds three fixtures under
  crates/code-intel-cli/tests/fixtures/audit/ (a nonexistent evidence path,
  a reversed line range, and a report that fabricates "high" coverage for
  departments it never assessed) plus three cli_tests.rs cases asserting
  `code-intel audit --operation validate` rejects each one.

cargo build -p code-intel, cargo test -p code-intel, and cargo fmt -p
code-intel -- --check all pass. The PS1 edits were verified to parse and the
existing tests/test-model-channel-delegate.ps1 suite still passes; the new
byte-budget behavior was additionally verified against a fake runaway
process producing 12.5MB of output (truncated in 625ms instead of waiting
out the timeout).
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@2233admin, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ae701ed1-23d8-4a6e-9311-7760e3034bee

📥 Commits

Reviewing files that changed from the base of the PR and between b73c16a and bff15b6.

📒 Files selected for processing (9)
  • Invoke-ModelChannelDelegate.ps1
  • crates/code-intel-cli/src/audit_report/cli_tests.rs
  • crates/code-intel-cli/tests/fixtures/audit/fabricated-coverage-claim.json
  • crates/code-intel-cli/tests/fixtures/audit/invalid-evidence-path.json
  • crates/code-intel-cli/tests/fixtures/audit/invalid-line-range.json
  • docs/audit-report.md
  • orchestration/audit/prompts/ai-safety.md
  • orchestration/audit/prompts/security.md
  • orchestration/audit/prompts/supply-chain.md

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.

@2233admin
2233admin merged commit 0a8f27f into main Jul 27, 2026
6 checks passed
@2233admin
2233admin deleted the fix/ai-safety-hardening branch July 27, 2026 18:24
2233admin added a commit that referenced this pull request Jul 28, 2026
…ing/facades, CI gates that gate, docs drift (#60)

* fix(security): disarm scanned-repo git config execution in live sibling scripts

Extend run-code-intel.ps1's GitHardening pattern (core.fsmonitor, core.hooksPath,
core.sshCommand, diff.external, core.pager pinned empty + GIT_CONFIG_NOSYSTEM=1)
to every git invocation in Invoke-ScopedRepowise.ps1 (incl. the worktree-mutating
checkout/reset/clean path), Invoke-CodeNexusLite.ps1, OpenSpec-Detector.ps1, and
Invoke-SentruxAgentTool.ps1. Booby-trapped fixture in the scoped-repowise security
test proves fsmonitor/hooksPath no longer fire.

Closes the security-001 residual documented in #33.

* fix(rust): correctness and contract fixes in the code-intel core

- structured_edit/providers: resolve ast-grep and repowise through tool_path to
  absolute paths (with .cmd/.bat shim wrapping) instead of bare-name spawns with
  cwd inside the scanned repo
- tool_path: skip relative PATH entries so locate() only returns absolute paths
- hardened_git: inject -c core.quotepath=false so non-ASCII paths are emitted
  verbatim (fixes silent drops in audit scope and sentrux git signals)
- change_impact/artifact_ref: replace element-shape unwrap panics with exit-65
  contract errors; validate_native_array_artifact now validates element fields
- capability_inventory: resolve the workflow-recommendation facade via
  discover_manifest instead of compile-time CARGO_MANIFEST_DIR
- main: add four missing routes to FULL_HELP_TEXT (audit, compatibility
  retirement-ticket, provider codenexus-adapt, repository survival-scan)
- sentrux_gate: require gated metric keys present+numeric in baselines instead
  of silently comparing against 0.0
- artifact_index: replace remove-then-rename with bak-swap so index.json is
  recoverable at every instant
- audit_report tests: adversarial fixtures now assert the specific rejection
  reason, not just exit 65
- orchestration records: re-sync toolchain/conformance digest pins to the
  edited sources

* fix(ps1): launcher and wrapper defects on the live path

- run-code-intel.ps1: model-routing adoption was dead code (provider normalized
  to non-empty before the intake guard checked for emptiness) - routed
  provider/model now win unless the operator explicitly overrode them
- update-code-intel-index.ps1: resolve the binary via CODE_INTEL_RUST_CLI,
  target/release, target/debug, then PATH instead of requiring a debug build
  that no installer or release ever produces
- invoke-code-intel.ps1: load the default pipeline.config.json for the plain
  -RepoPath shape (artifactRoot was silently dropped); stop rejecting
  PowerShell common parameters as unsupported options
- check-code-intel-tools.ps1: CODE_INTEL_HOME check compared the env var
  against itself; now checks the directory exists and flags divergence from
  the default derivation
- install-code-intel-pipeline.ps1: pin repowise (==0.36.0) instead of
  unpinned --upgrade (supply-chain-003 in #35)

* fix(ci): make the gates gate

- ci.yml: execute the ten previously never-run PS1 suites (incl. the PR #44
  model-delegate ai-safety regression suite and the conformance-evidence
  suites); add the two large PS1 entry points to both parser-check lists;
  pin choco ripgrep to 14.1.0 in both install sites (supply-chain-002)
- parity-observe.yml: provision sentrux + PATH before the parity harness (its
  only evidenced comparison was structurally vacuous without it); pin actions
  to commit SHAs and ripgrep to 14.1.0 (restores #43 hardening)
- skill-check.yml: link check now actually fails on broken relative links;
  darwin score gains the missing checkpoint_design scoring branch and drops
  the unused ANTHROPIC_API_KEY

test-run-commit-contract.ps1 is wired continue-on-error: it fails at HEAD with
'facade published an incoherent A07 marker' - pre-existing defect, tracked
separately.

* docs: align claims with shipped behavior

- README: the un-flagged run-code-intel.ps1 default is the legacy scanner
  (Rust DAG is opt-in via -DagCoordinate), not the inverse; artifact/read-flow
  sections now distinguish primary-entry DAG outputs from legacy-path
  artifacts; document the 0.6.0 'code-intel audit' command
- follow-up-automation: emission and policy reading happen only on the legacy
  runner; the compiled primary entry does neither
- code-intel-architecture: sentrux Pro activation is SENTRUX_AUTO_PRO=1
  opt-in, not automatic
- public-beta: document release attestation verification with gh attestation
  verify (supply-chain-007 in #35)

* style: rustfmt the new test and validation code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant