-
Notifications
You must be signed in to change notification settings - Fork 136
Add prototype pollution protection to parseJsonWithRepair with stack-based algorithm #15142
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
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
- Add sanitizePrototypePollution function to remove dangerous keys - Integrate sanitization into parseJsonWithRepair in both success and repair paths - Add comprehensive tests covering basic, nested, array, and edge case scenarios - All existing tests pass with new protection in place Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
All checks pass: - Build successful - All unit tests pass (67 json_repair_helpers + 102 collect_ndjson_output) - Formatting validated - Linting passes - Code review completed Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
| * sanitizePrototypePollution({outer: {__proto__: {bad: true}, safe: "value"}}) | ||
| * // Returns: {outer: {safe: "value"}} | ||
| */ | ||
| function sanitizePrototypePollution(obj) { |
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.
@copilot use stack based algo instead of recursion, protect against recursive object tree
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.
Converted to stack-based algorithm with WeakMap for circular reference tracking. This prevents stack overflow from deeply nested structures and handles circular references safely. Commit 693338c.
| * sanitizePrototypePollution({outer: {__proto__: {bad: true}, safe: "value"}}) | ||
| * // Returns: {outer: {safe: "value"}} | ||
| */ | ||
| function sanitizePrototypePollution(obj) { |
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.
@copilot add more tests for this function
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.
Added 9 new tests covering:
- Circular references (simple, nested, with dangerous keys)
- Very deep nesting (1000 levels)
- Mixed circular and nested structures
- Repeated object references
- Array circular references
- Malicious deeply nested attack with circularity
Total: 76 tests (up from 67). Commit 693338c.
…ircular reference tests - Replace recursive implementation with iterative stack-based approach - Add WeakMap to track visited objects and handle circular references - Protect against stack overflow from deeply nested malicious structures - Add 9 new tests for circular references, deep nesting (1000 levels), and complex scenarios - All 76 tests pass (67 original + 9 new) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
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.
Pull request overview
This PR adds critical security protection against prototype pollution attacks in the safe-outputs collection pipeline. The implementation uses a stack-based iterative algorithm with WeakMap-based circular reference tracking to safely sanitize JSON parsed from untrusted agent outputs before they are merged using Object.assign().
Changes:
- Implemented
sanitizePrototypePollution()function with stack-based traversal to remove dangerous keys (__proto__,constructor,prototype) - Integrated sanitization into
parseJsonWithRepair()in both success and error-recovery paths - Added 76 comprehensive test cases covering edge cases, circular references, deep nesting, and real-world attack scenarios
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/json_repair_helpers.cjs | Implements the core sanitizePrototypePollution() function using stack-based traversal with WeakMap for circular reference handling |
| actions/setup/js/json_repair_helpers.test.cjs | Adds comprehensive test suite (76 tests) covering basic sanitization, nested objects, arrays, primitives, edge cases, circular references, and integration patterns |
| actions/setup/js/collect_ndjson_output.cjs | Integrates sanitizePrototypePollution() into both success and repair paths of parseJsonWithRepair() |
| docs/src/content/docs/agent-factory-status.mdx | Removes Bot Detection Agent workflow entry (unrelated to PR purpose) |
| docs/src/content/docs/reference/frontmatter-full.md | Updates documentation for update-issue body field backward compatibility (unrelated to PR purpose) |
| .github/workflows/workflow-generator.lock.yml | Updates MCP tool description to mention body updates are allowed (unrelated to PR purpose) |
| .github/workflows/poem-bot.lock.yml | Updates MCP tool description to mention body updates are allowed (unrelated to PR purpose) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | [Basic Research Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/research.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/research.lock.yml) | - | - | | ||
| | [Blog Auditor](https://github.com/github/gh-aw/blob/main/.github/workflows/blog-auditor.md) | claude | [](https://github.com/github/gh-aw/actions/workflows/blog-auditor.lock.yml) | - | - | | ||
| | [Bot Detection Agent 🔍🤖](https://github.com/github/gh-aw/blob/main/.github/workflows/bot-detection.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/bot-detection.lock.yml) | - | - | | ||
| | [Brave Web Search Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/brave.md) | copilot | [](https://github.com/github/gh-aw/actions/workflows/brave.lock.yml) | - | `/brave` | |
Copilot
AI
Feb 12, 2026
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.
This file change appears to be unrelated to the PR's stated purpose of adding prototype pollution protection. The removal of the Bot Detection Agent workflow entry should be included in a separate PR or explained in the PR description if it's intentional.
| }, | ||
| { | ||
| "description": "Update an existing GitHub issue's status, title, labels, assignees, milestone, or body. Body updates support replacing, appending to, prepending content, or updating a per-run \"island\" section. CONSTRAINTS: Maximum 1 issue(s) can be updated.", | ||
| "description": "Update an existing GitHub issue's status, title, labels, assignees, milestone, or body. Body updates support replacing, appending to, prepending content, or updating a per-run \"island\" section. CONSTRAINTS: Maximum 1 issue(s) can be updated. Body updates are allowed.", |
Copilot
AI
Feb 12, 2026
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.
This change to the MCP tool description appears to be unrelated to the PR's stated purpose of adding prototype pollution protection. The addition of "Body updates are allowed." should be included in a separate PR or explained in the PR description if it's related to the documentation changes in frontmatter-full.md.
| }, | ||
| { | ||
| "description": "Update an existing GitHub issue's status, title, labels, assignees, milestone, or body. Body updates support replacing, appending to, prepending content, or updating a per-run \"island\" section. CONSTRAINTS: Maximum 2 issue(s) can be updated. Target: *.", | ||
| "description": "Update an existing GitHub issue's status, title, labels, assignees, milestone, or body. Body updates support replacing, appending to, prepending content, or updating a per-run \"island\" section. CONSTRAINTS: Maximum 2 issue(s) can be updated. Target: *. Body updates are allowed.", |
Copilot
AI
Feb 12, 2026
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.
This change to the MCP tool description appears to be unrelated to the PR's stated purpose of adding prototype pollution protection. The addition of "Body updates are allowed." should be included in a separate PR or explained in the PR description if it's related to the documentation changes in frontmatter-full.md.
| # Allow updating issue body. Set to true to enable body updates, false to disable. | ||
| # For backward compatibility, null (body:) also enables body updates. | ||
| # (optional) | ||
| body: null |
Copilot
AI
Feb 12, 2026
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.
This documentation change about the 'body' field parsing behavior appears to be unrelated to the PR's stated purpose of adding prototype pollution protection. While this clarifies the backward compatibility behavior for body field parsing (null values enabling body updates), it should be included in a separate PR or explained in the PR description.
🔍 PR Triage ResultsCategory: Security Bug | Risk: High | Priority: 95/100 Scores Breakdown
📋 Recommended Action: Fast-trackThis PR addresses a critical security vulnerability in the safe-outputs collection pipeline. The prototype pollution vulnerability could allow malicious agent outputs to pollute JavaScript object prototypes, potentially leading to privilege escalation or data manipulation. Key strengths:
Next steps:
Triaged by PR Triage Agent on 2026-02-12
|
Problem
The
parseJsonWithRepairfunction in the safe-outputs collection pipeline parses untrusted JSON from agent outputs, which is then merged into existing objects viaObject.assign(). WhileJSON.parse()itself is safe, the subsequent merge operations are vulnerable to prototype pollution if the parsed object contains keys like__proto__,constructor, orprototype.Changes
Security Function
Added
sanitizePrototypePollution()tojson_repair_helpers.cjs:__proto__,constructor,prototypeWeakMapto track visited objects and handle circular referencesIntegration
Modified
parseJsonWithRepair()incollect_ndjson_output.cjsto sanitize parsed objects in both success and repair paths:Test Coverage
Added 76 test cases covering:
{"type": "create_issue", "__proto__": {"isAdmin": true}})Object.assign(), spread operator, array pushTechnical Advantages
Example Protection
Before:
After:
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.