SEC-005: deliver Agent SDK prompts verbatim (verbatim_prompts=True) - #146
Merged
Merged
Conversation
claude-agent-sdk 0.2.158 added ClaudeAgentOptions.verbatim_prompts. By default the Claude CLI pre-processes each user message before the model sees it: an @path mention anywhere in the text is expanded into that file's contents, and a leading "/" is dispatched as a slash command. That runs before tools=[], allowed_tools and permission_mode="dontAsk" are consulted, so the existing tool boundary never sees it. The IPO extraction prompt inlines the company name scraped from SEBI listings, so a filing named like "@/etc/passwd" could make the CLI read a local file into the model's context. All four runners (Check Fundamentals, Technical Analysis, 67 Ka Funda, IPO extraction) now set verbatim_prompts=True; the other three prompts carry only app-owned values but share one contract. The option is not feature-detected: an SDK older than the pin raises TypeError, so AI runs fail closed rather than silently dropping the control. The runner tests use permissive fake options classes, so a new test builds the real pinned ClaudeAgentOptions to make an SDK downgrade fail CI. The CLI half (Claude Code 2.1.248+) is satisfied by the CLI 2.1.281 bundled with the 0.2.159 pin, which the SDK prefers over any claude on PATH; the ADR records that an older CLI would ignore the flag with only a warning. Docs: the ai-execution-boundaries ADR gains the decision, rejected options, consequences and verification contract; the security LLD, HLD and the four agent LLDs list the option in their SDK containment contract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SEC-005 sets
verbatim_prompts=Trueon all four Claude Agent SDK runners (Check Fundamentals, Technical Analysis, 67 Ka Funda, IPO extraction). The option was added in claude-agent-sdk 0.2.158;mainpins 0.2.159 since #142.Why: by default the Claude CLI pre-processes each user message before the model sees it. An
@pathmention anywhere in the text is expanded into that file's contents (likewise@server:resourceMCP mentions), and a message starting with/is dispatched as a slash command. This runs beforetools=[],allowed_toolsandpermission_mode="dontAsk"are consulted, so the existing tool boundary never sees it.The IPO extraction prompt inlines the company name scraped from SEBI listings. A filing named like
@/etc/passwdcould make the CLI read a local file into the model's context. The other three prompts carry only app-owned values (symbol, run mode, model name, candle-derived price facts); they get the same setting so the contract has no per-agent exceptions.Two corrections to the original ticket text, both verified in code:
_build_user_promptinlines the classifier's section enum values and page numbers, not free-text PDF headings. The only untrusted free text is the company name./, and every prompt starts with fixed app text. So@pathexpansion is the live path today; the option closes both.Failure modes on version skew
TypeErrorextraction_failedreceipt).PATH(checked withclaude.exe --versionin a pinned venv). Documented in the ADR.The option is deliberately not feature-detected (unlike the fast-mode
ThinkingConfigDisabled): silently running without a security control would reopen the pre-tool file-read path.Changes
verbatim_prompts=Truekwarg plus a Beginner-note comment in each of the fourClaudeAgentOptionsconstructions (the only four in the repo).verbatim_prompts is True.test_pinned_sdk_accepts_verbatim_promptsbuilds the real pinnedClaudeAgentOptions. The runner tests use fake options classes that accept any keyword, so without it a pin downgrade below 0.2.158 would pass CI and break every AI screener at run time.ai-execution-boundaries.mdADR: decision, two rejected options (app-side@//scrubbing; feature detection), consequences, verification contract.security.mdgets a decision row and a testing bullet.Verification
KeyError: 'verbatim_prompts'. The real-SDK guard failed withTypeError: ... unexpected keyword argument 'verbatim_prompts'on a local SDK 0.2.154.constraints.txt(SDK 0.2.159, SQLAlchemy 2.1.0, numpy 2.5.3), Python 3.13:pre_commit validate-config: OKpip_audit -r constraints.txt: exit 0git diff origin/main -- constraints.txt pyproject.toml requirements*.txtis empty./code-review(high) found 6 items:/commandrisk was overstated; one ADR line broke the wrap./security-review: no findings. The change strictly narrows the attack surface and adds no new data flow.Not done (flagged for the reviewer)
setting_sources=[]already drops CLAUDE.md, and each agent has at most three small MCP tools. But only a real run exercises it, because every unit test fakes the SDK. Suggested pre-merge check: run one Check Fundamentals analysis and confirm it still callsfetch_company_data.backend/ai_runtime.pywould let a new agent inherit them. Left as a follow-up to keep this PR to one ticket.TypeErroron every AI run after this merges. Upgrade withpython -m pip install -c constraints.txt claude-agent-sdk.🤖 Generated with Claude Code