-
Notifications
You must be signed in to change notification settings - Fork 12
t4954: Add section 8.4 column-level query discipline and URL credential detection #4956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -244,7 +244,7 @@ _pg_load_yaml_patterns() { | |||||
| # data_exfiltration, data_exfiltration_dns, context_manipulation, | ||||||
| # homoglyph, unicode_manipulation, fake_role, comment_injection, | ||||||
| # priority_manipulation, fake_delimiter, split_personality, | ||||||
| # steganographic, fake_conversation | ||||||
| # steganographic, fake_conversation, credential_exposure | ||||||
|
|
||||||
| # YAML pattern file path (Lasso-compatible format) | ||||||
| PROMPT_GUARD_YAML_PATTERNS="${PROMPT_GUARD_YAML_PATTERNS:-}" | ||||||
|
|
@@ -327,6 +327,14 @@ LOW|unicode_manipulation|Mixed script with injection|\p{Cyrillic}[\x00-\x7F]*(ns | |||||
| LOW|steganographic|Acrostic instruction pattern|[A-Z][a-z]+\s*\n[A-Z][a-z]+\s*\n[A-Z][a-z]+\s*\n[A-Z][a-z]+\s*\n[A-Z][a-z]+ | ||||||
| LOW|system_prompt_extraction|System prompt extraction variant|([Ww]rite|[Tt]ype|[Oo]utput)\s+(out\s+)?(the\s+)?(text|content|words)\s+(above|before|preceding)\s+(this|my)\s+(message|input|prompt) | ||||||
| LOW|system_prompt_extraction|Prompt leak via translation|([Tt]ranslate|[Cc]onvert)\s+(your\s+)?(system\s+)?(prompt|instructions|rules)\s+(to|into)\s+(French|Spanish|Chinese|another\s+language) | ||||||
| MEDIUM|credential_exposure|URL query param: secret|[?&]secret=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: token|[?&]token=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: key|[?&](api_key|apikey|api-key)=[^&\s]{8,} | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are a couple of inconsistencies on this line:
To ensure all documented credential parameters are detected, please update the pattern and description for consistency.
Suggested change
References
|
||||||
| MEDIUM|credential_exposure|URL query param: password|[?&]password=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: access_token|[?&]access_token=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: auth|[?&](auth|authorization)=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: client_secret|[?&]client_secret=[^&\s]{8,} | ||||||
| MEDIUM|credential_exposure|URL query param: webhook_secret|[?&]webhook_secret=[^&\s]{8,} | ||||||
| PATTERNS | ||||||
| return 0 | ||||||
| } | ||||||
|
|
@@ -579,6 +587,10 @@ _pg_sanitize_message() { | |||||
| # Strip long unicode escape sequences | ||||||
| sanitized=$(printf '%s' "$sanitized" | sed -E 's/(\\u[0-9a-fA-F]{4}){4,}/[unicode-filtered]/g') | ||||||
|
|
||||||
| # Redact credential values in URL query parameters (t4954) | ||||||
| # Matches ?secret=VALUE or &token=VALUE etc. and replaces VALUE with [REDACTED] | ||||||
| sanitized=$(printf '%s' "$sanitized" | sed -E 's/([?&](secret|token|api_key|apikey|api-key|password|access_token|auth|authorization|client_secret|webhook_secret)=)[^&[:space:]]{8,}/\1[REDACTED]/g') | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The sanitization regex is missing the
Suggested change
References
|
||||||
|
|
||||||
| printf '%s' "$sanitized" | ||||||
| return 0 | ||||||
| } | ||||||
|
|
@@ -1479,6 +1491,39 @@ cmd_test() { | |||||
| echo "Testing URL encoded payload (MEDIUM — should WARN):" | ||||||
| _test_expect "URL encoded payload" 2 "Check this: %69%67%6E%6F%72%65%20%70%72%65%76%69%6F%75%73" | ||||||
|
|
||||||
| echo "" | ||||||
| echo "Testing URL credential exposure (MEDIUM — should WARN, t4954):" | ||||||
| _test_expect "URL with ?secret= param" 2 "https://example.com/webhook?secret=abc123def456ghi789" | ||||||
| _test_expect "URL with &token= param" 2 "https://api.example.com/callback?id=1&token=FAKE_SK_LIVE_abcdef123456" | ||||||
| _test_expect "URL with ?api_key= param" 2 "https://hooks.example.com/v1?api_key=FAKE_AKIA_IOSFODNN7EXAMPLE" | ||||||
| _test_expect "URL with ?password= param" 2 "https://service.example.com/auth?password=SuperSecret123!" | ||||||
| _test_expect "URL with ?access_token= param" 2 "https://api.example.com/data?access_token=FAKE_JWT_aGVhZGVyLnBheWxvYWQ" | ||||||
| _test_expect "URL with ?client_secret= param" 2 "https://oauth.example.com/token?client_secret=FAKE_CS_abcdef123456789" | ||||||
| _test_expect "Short param value (no match)" 0 "https://example.com/page?secret=abc" | ||||||
|
|
||||||
| echo "" | ||||||
| echo "Testing URL credential sanitization (t4954):" | ||||||
| total=$((total + 1)) | ||||||
| local url_sanitized | ||||||
| url_sanitized=$(PROMPT_GUARD_QUIET="true" cmd_sanitize "Webhook URL: https://example.com/hook?secret=abc123def456ghi789&name=test" 2>/dev/null) | ||||||
| if [[ "$url_sanitized" == *"[REDACTED]"* ]] && [[ "$url_sanitized" != *"abc123def456ghi789"* ]]; then | ||||||
| echo -e " ${GREEN}PASS${NC} URL secret param redacted in sanitization" | ||||||
| passed=$((passed + 1)) | ||||||
| else | ||||||
| echo -e " ${RED}FAIL${NC} URL secret param not redacted: $url_sanitized" | ||||||
| failed=$((failed + 1)) | ||||||
| fi | ||||||
|
|
||||||
| total=$((total + 1)) | ||||||
| url_sanitized=$(PROMPT_GUARD_QUIET="true" cmd_sanitize "Config: https://api.example.com/v1?token=sk_live_abcdef123456&format=json" 2>/dev/null) | ||||||
| if [[ "$url_sanitized" == *"[REDACTED]"* ]] && [[ "$url_sanitized" == *"format=json"* ]]; then | ||||||
| echo -e " ${GREEN}PASS${NC} URL token param redacted, non-secret params preserved" | ||||||
| passed=$((passed + 1)) | ||||||
| else | ||||||
| echo -e " ${RED}FAIL${NC} URL token sanitization incorrect: $url_sanitized" | ||||||
| failed=$((failed + 1)) | ||||||
| fi | ||||||
|
|
||||||
| # ── scan-stdin tests ──────────────────────────────────────── | ||||||
|
|
||||||
| echo "" | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with the new rule in
.agents/prompts/build.txt(section 8.4, line 295), which mentions?key=, this pattern should also detectkey=. The current pattern only detectsapi_key,apikey, andapi-key. The description should also be updated to reflect this change.References
key=) for comprehensive security detection and sanitization.key=) is identified, all relevant detection and sanitization logic across the codebase is updated.