Skip to content

Conversation

@oioki
Copy link
Member

@oioki oioki commented Jan 19, 2026

Summary

Implements support for Cross-Origin-Opener-Policy (COOP) reports in Relay, following the same pattern as Network Error Logging (NEL) reports. COOP reports are sent by browsers when cross-origin isolation policies are violated, helping developers identify and fix security issues.

Changes

  • ✅ Add COOP protocol definitions (relay-event-schema/src/protocol/coop.rs)
  • ✅ Add /api/{project_id}/coop/ endpoint for receiving reports
  • ✅ Add COOP processor to convert reports to log events
  • ✅ Add COOP normalization with violation type mapping to human-readable messages
  • ✅ Add COOP item type to envelope processing pipeline
  • ✅ Add integration tests for COOP report handling

Implementation Details

COOP reports are converted to log events with:

  • Origin: auto.http.browser_report.coop
  • Severity: error (enforce mode) or warn (report-only mode)
  • Attributes: disposition, effective policy, violation type, URLs, source location

Supported violation types:

  • navigate-to-document / navigate-from-document - Browsing context group switches
  • access-from-coop-page-to-* - Blocked outbound access attempts
  • access-to-coop-page-from-* - Blocked inbound access attempts

Architecture

Follows the NEL report pattern:

  1. Browser sends COOP report to /api/{project_id}/coop/
  2. Report is wrapped in envelope with ItemType::Coop
  3. Processor converts to log event with structured attributes
  4. Normalizer maps violation types to descriptive messages
  5. Log is stored in the logs product

Test plan

  • Code compiles successfully (cargo check)
  • Integration tests added for both navigation and access violations
  • Manual testing can be done by configuring COOP headers:
Cross-Origin-Opener-Policy: same-origin; report-to="coop-endpoint"
Report-To: {"group":"coop-endpoint","max_age":86400,"endpoints":[{"url":"https://relay.example.com/api/PROJECT_ID/coop/?sentry_key=KEY"}]}

Testing checklist

  • Run integration tests: pytest tests/integration/test_coop.py -v
  • Verify COOP reports are converted to logs with correct attributes
  • Verify log levels match disposition (enforce=error, reporting=warn)
  • Verify all violation types have proper message mapping

References

🤖 Generated with Claude Code

Implements support for COOP reports following the Reporting API specification,
similar to the existing NEL (Network Error Logging) implementation.

Changes:
- Add COOP protocol definitions and report structures
- Add /api/{project_id}/coop/ endpoint for receiving reports
- Add COOP processor to convert reports to log events
- Add COOP normalization with violation type mapping
- Add COOP item type to envelope processing
- Add integration tests for COOP report handling

COOP reports are converted to log events with appropriate attributes
and severity levels based on the disposition (enforce vs reporting).

Supported violation types:
- navigate-to-document / navigate-from-document
- access-from-coop-page-to-* / access-to-coop-page-from-*

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@oioki oioki requested a review from a team as a code owner January 19, 2026 18:08
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

}
} else {
OurLogLevel::Warn
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use-after-move: body.disposition accessed after being consumed

High Severity

The body.disposition field is moved at line 110 via map_value(self, ...) which takes ownership. Later at line 134, the code attempts to access body.disposition.value() to determine the log level, but this value has already been consumed. This is a use-after-move ownership violation. The NEL implementation avoids this by extracting values needed later (like error_type) before moving fields. The fix is to either clone body.disposition before calling map_value, or extract the disposition value earlier for reuse in both the attribute and level determination.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants