-
Notifications
You must be signed in to change notification settings - Fork 0
security: reconstruct exact HTTP method strings on protected main #204
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
base: main
Are you sure you want to change the base?
Changes from all commits
e9638ef
2428bef
45b2bda
4af871e
67d7e8d
58e36fa
5b62c18
ab51ef1
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 |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| """Regression tests for exact built-in HTTP method policy values.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
|
|
||
| from egressweave.policy import EgressPolicy | ||
|
|
||
|
|
||
| class _NonExactMethod(str): | ||
| """Keep subclass identity if trusted normalization invokes polymorphic methods.""" | ||
|
|
||
| def strip(self, chars: str | None = None) -> _NonExactMethod: | ||
| """Return this subclass instead of a canonical built-in string.""" | ||
| return self | ||
|
|
||
| def upper(self) -> _NonExactMethod: | ||
| """Return this subclass instead of a canonical built-in string.""" | ||
| return self | ||
|
Comment on lines
+12
to
+21
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. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 정규화가 호출되지 않았음을 검증하도록 테스트를 강화하십시오.
수정 예시 class _NonExactMethod(str):
- """Keep subclass identity if trusted normalization invokes polymorphic methods."""
+ """Fail if normalization invokes subclass-controlled methods."""
def strip(self, chars: str | None = None) -> _NonExactMethod:
- """Return this subclass instead of a canonical built-in string."""
- return self
+ """Fail when trusted code invokes subclass-controlled stripping."""
+ raise AssertionError("string subclass strip executed")
def upper(self) -> _NonExactMethod:
- """Return this subclass instead of a canonical built-in string."""
- return self
+ """Fail when trusted code invokes subclass-controlled uppercasing."""
+ raise AssertionError("string subclass upper executed")Also applies to: 32-38, 68-75 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| class _ExplodingMethodList(str): | ||
| """Expose polymorphic dispatch in comma-separated method parsing.""" | ||
|
|
||
| def split(self, sep: str | None = None, maxsplit: int = -1) -> list[str]: | ||
| """Fail if trusted construction invokes subclass-controlled splitting.""" | ||
| raise AssertionError("string subclass split executed") | ||
|
|
||
|
|
||
| def test_method_policy_rejects_str_subclass_before_normalization() -> None: | ||
| """Reject subclass-controlled method normalization during policy construction.""" | ||
| with pytest.raises(TypeError, match="allowed_methods"): | ||
| EgressPolicy.from_hosts( | ||
| "api.example.com", | ||
| allowed_methods={_NonExactMethod("GET")}, | ||
| ) | ||
|
|
||
|
|
||
| def test_direct_policy_rejects_str_subclass_before_comma_split() -> None: | ||
| """Reject a direct comma-string subclass before invoking its split method.""" | ||
| with pytest.raises(TypeError, match="allowed_methods"): | ||
| EgressPolicy( | ||
| allowed_hosts=frozenset({"api.example.com"}), | ||
| allowed_methods=_ExplodingMethodList("GET,POST"), | ||
| ) | ||
|
|
||
|
|
||
| def test_from_hosts_rejects_str_subclass_before_comma_split() -> None: | ||
| """Reject a host-factory comma-string subclass before invoking split.""" | ||
| with pytest.raises(TypeError, match="allowed_methods"): | ||
| EgressPolicy.from_hosts( | ||
| "api.example.com", | ||
| allowed_methods=_ExplodingMethodList("GET,POST"), | ||
| ) | ||
|
|
||
|
|
||
| def test_from_authorities_rejects_str_subclass_before_comma_split() -> None: | ||
| """Reject an authority-factory comma-string subclass before invoking split.""" | ||
| with pytest.raises(TypeError, match="allowed_methods"): | ||
| EgressPolicy.from_authorities( | ||
| [("api.example.com", 443)], | ||
| allowed_methods=_ExplodingMethodList("GET,POST"), | ||
| ) | ||
|
|
||
|
|
||
| def test_runtime_method_authorization_rejects_str_subclass_before_normalization() -> None: | ||
| """Reject subclass-controlled normalization at the request authorization boundary.""" | ||
| policy = EgressPolicy.from_hosts( | ||
| "api.example.com", | ||
| allowed_methods={"GET"}, | ||
| ) | ||
|
|
||
| assert policy.allows_http_method(_NonExactMethod("GET")) is False | ||
|
|
||
|
|
||
| def test_policy_configuration_integrity_guide_covers_exact_method_strings() -> None: | ||
| """Document the exact HTTP method value boundary and preserved string syntax.""" | ||
| guide = Path("docs/research/policy-configuration-integrity.md").read_text( | ||
| encoding="utf-8" | ||
| ) | ||
|
|
||
| assert "exact built-in `str`" in guide | ||
| assert "HTTP method" in guide | ||
| assert "comma-separated" in guide | ||
| assert "does not make EgressWeave a Python sandbox" in guide | ||
|
|
||
|
|
||
| def test_changelog_records_http_method_value_sealing() -> None: | ||
| """Record the method-string policy tightening in release history.""" | ||
| changelog = Path("CHANGELOG.md").read_text(encoding="utf-8") | ||
|
|
||
| assert "Reject non-exact string subclasses in HTTP method policy values" in changelog | ||
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.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: ContextualWisdomLab/EgressWeave
Length of output: 32023
🏁 Script executed:
Repository: ContextualWisdomLab/EgressWeave
Length of output: 50388
🏁 Script executed:
Repository: ContextualWisdomLab/EgressWeave
Length of output: 14231
allowed_methods를 검증한 후frozenset으로 변환하세요.from_hosts와from_authorities는 exact-type 검증 전에 iterable을 집합으로 변환합니다. 이 과정에서str서브클래스의__hash__가 실행될 수 있습니다. 각 원소를_normalize_allowed_method로 먼저 검증하고 정규화된 값만frozenset에 넣으세요.📍 Affects 1 file
src/egressweave/policy.py#L381-L381(this comment)src/egressweave/policy.py#L444-L444🤖 Prompt for AI Agents