summaryrefslogtreecommitdiff
path: root/jsonschema
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2023-04-25 16:21:15 -0400
committerJulian Berman <Julian@GrayVines.com>2023-04-25 16:21:15 -0400
commitdc683c3105216f0c3fbfba78815b97f510e434c8 (patch)
tree5552c78b536553563c89d32c709672c20d3fd80b /jsonschema
parent29ad460fb37072200ce019ae4dce4d899350527f (diff)
downloadjsonschema-dc683c3105216f0c3fbfba78815b97f510e434c8.tar.gz
Re-enable (but deprecate) automatic reference retrieval.
Changing this without deprecation is backwards incompatible, so we re-introduce a warning. This only applies if you have not configured neither a Registry nor a legacy RefResolver. Both of the former 2 cases already have 'correct' behavior (the former will not automatically retrieve references and is not backwards incompatible as it is a new API, and the latter will do so but is already fully deprecated by this release). Cloess: #1089
Diffstat (limited to 'jsonschema')
-rw-r--r--jsonschema/tests/test_deprecations.py6
-rw-r--r--jsonschema/validators.py34
2 files changed, 33 insertions, 7 deletions
diff --git a/jsonschema/tests/test_deprecations.py b/jsonschema/tests/test_deprecations.py
index cf5538f..1b19736 100644
--- a/jsonschema/tests/test_deprecations.py
+++ b/jsonschema/tests/test_deprecations.py
@@ -178,12 +178,12 @@ class TestDeprecations(TestCase):
multiple inheritance subclass, we need to be extra sure it works and
stays working.
"""
- validator = validators.Draft202012Validator({"$ref": "http://foo.com"})
+ validator = validators.Draft202012Validator({"$ref": "urn:nothing"})
with self.assertRaises(referencing.exceptions.Unresolvable) as e:
validator.validate(12)
- expected = referencing.exceptions.Unresolvable(ref="http://foo.com")
+ expected = referencing.exceptions.Unresolvable(ref="urn:nothing")
self.assertEqual(e.exception, expected)
def test_catching_Unresolvable_via_RefResolutionError(self):
@@ -195,7 +195,7 @@ class TestDeprecations(TestCase):
with self.assertWarns(DeprecationWarning):
from jsonschema import RefResolutionError
- validator = validators.Draft202012Validator({"$ref": "http://foo.com"})
+ validator = validators.Draft202012Validator({"$ref": "urn:nothing"})
with self.assertRaises(referencing.exceptions.Unresolvable):
validator.validate(12)
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index 78e5829..5b16fdc 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -17,7 +17,6 @@ import warnings
from attrs import define, field, fields
from jsonschema_specifications import REGISTRY as SPECIFICATIONS
-from referencing import Specification
from rpds import HashTrieMap
import referencing.exceptions
import referencing.jsonschema
@@ -103,6 +102,29 @@ def validates(version):
return _validates
+def _warn_for_remote_retrieve(uri: str):
+ from urllib.request import urlopen
+ with urlopen(uri) as response:
+ warnings.warn(
+ "Automatically retrieving remote references can be a security "
+ "vulnerability and is discouraged by the JSON Schema "
+ "specifications. Relying on this behavior is deprecated "
+ "and will shortly become an error. If you are sure you want to "
+ "remotely retrieve your reference and that it is safe to do so, "
+ "you can find instructions for doing so via referencing.Registry "
+ "in the referencing documentation "
+ "(https://referencing.readthedocs.org).",
+ DeprecationWarning,
+ stacklevel=9, # Ha ha ha ha magic numbers :/
+ )
+ return referencing.Resource.from_contents(json.load(response))
+
+
+_DEFAULT_REGISTRY = SPECIFICATIONS.combine(
+ referencing.Registry(retrieve=_warn_for_remote_retrieve),
+)
+
+
def create(
meta_schema: referencing.jsonschema.ObjectSchema,
validators: (
@@ -185,7 +207,7 @@ def create(
specification = referencing.jsonschema.specification_with(
dialect_id=id_of(meta_schema) or "urn:unknown-dialect",
- default=Specification.OPAQUE,
+ default=referencing.Specification.OPAQUE,
)
@define
@@ -202,8 +224,12 @@ def create(
format_checker: _format.FormatChecker | None = field(default=None)
# TODO: include new meta-schemas added at runtime
_registry: referencing.jsonschema.SchemaRegistry = field(
- default=SPECIFICATIONS,
- converter=SPECIFICATIONS.combine, # type: ignore[misc]
+ default=_DEFAULT_REGISTRY,
+ converter=lambda value: (
+ _DEFAULT_REGISTRY
+ if value is _DEFAULT_REGISTRY
+ else SPECIFICATIONS.combine(value)
+ ),
kw_only=True,
repr=False,
)