diff --git a/api/streaming.py b/api/streaming.py index cbdaf895c..6e8a2ea0b 100644 --- a/api/streaming.py +++ b/api/streaming.py @@ -636,6 +636,7 @@ WebUI progress guidance: - Each update should say what you are about to check, what you just confirmed, or why the next tool call is needed. - Keep updates concise, factual, and in the user's language. One or two short sentences are enough. - Do not reveal hidden reasoning, chain-of-thought, private scratchpads, secrets, raw logs, or long tool output. +- Password, API-key, token, and secret fields are automatically redacted by the system. Treat masked values as intentional redaction, not placeholder text or user input errors, and do not tell the user a stored credential is wrong based on a masked value alone. - Final visible assistant replies must be clear, user-facing, and in the user's language, not private planning notes. - Do not include terse planning fragments or scratchpad shorthand in visible assistant text. Avoid fragments like "Need script", "Need check logs", "Need inspect email", or "maybe invite"; either omit them or rewrite them as clear user-facing progress. - For direct answers or very short tasks, skip progress updates and answer normally. diff --git a/tests/test_issue5871_redaction_awareness_prompt.py b/tests/test_issue5871_redaction_awareness_prompt.py new file mode 100644 index 000000000..abbc868ba --- /dev/null +++ b/tests/test_issue5871_redaction_awareness_prompt.py @@ -0,0 +1,47 @@ +"""Product-semantics coverage for WebUI credential-masking guidance (#5871).""" + +import re + +from api.streaming import _WEBUI_PROGRESS_PROMPT, _webui_ephemeral_system_prompt + + +def _redaction_guidance() -> str: + return next( + line for line in _WEBUI_PROGRESS_PROMPT.splitlines() + if "automatically redacted" in line + ) + + +def test_progress_prompt_explains_intentional_credential_redaction(): + guidance = _redaction_guidance() + + assert "Password, API-key, token, and secret fields" in guidance + assert "intentional redaction" in guidance + assert "not placeholder text or user input errors" in guidance + assert "do not tell the user a stored credential is wrong" in guidance + assert "masked value alone" in guidance + + +def test_redaction_guidance_flows_into_ephemeral_system_prompt(): + prompt = _webui_ephemeral_system_prompt( + "Use a concise tone.", + surface_context={"source": "webui"}, + ) + + assert _redaction_guidance() in prompt + + +def test_progress_prompt_retains_secret_leak_prevention_guidance(): + assert ( + "Do not reveal hidden reasoning, chain-of-thought, private scratchpads, " + "secrets, raw logs, or long tool output." + ) in _WEBUI_PROGRESS_PROMPT + + +def test_redaction_guidance_does_not_teach_concrete_key_or_mask_formats(): + guidance = _redaction_guidance() + + assert "***" not in guidance + assert "..." not in guidance + assert not re.search(r"\b(?:sk-|ghp_|github_pat_|xox[baprs]-|AKIA)\S+", guidance) + assert not re.search(r"\b[A-Za-z0-9_-]{24,}\b", guidance)