parent
ad054fc694
commit
16875c747c
|
|
@ -1,3 +1,6 @@
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import jsonschema
|
||||
|
|
@ -333,7 +336,23 @@ class ConfigTemplate(
|
|||
is returned.
|
||||
"""
|
||||
if self.debug:
|
||||
return ''.join(traceback.format_exception(exc))
|
||||
# Strip deployment-specific path prefixes from File "..." lines to avoid disclosing
|
||||
# the server's filesystem layout. install_root covers all NetBox source files plus
|
||||
# any venv co-located inside the repo. When the venv lives outside the repo
|
||||
# (the typical production pattern, e.g. ~/.venv/netbox/), sys.prefix differs from
|
||||
# sys.base_prefix and the venv root is stripped separately so that the deployment
|
||||
# user's home directory is not exposed. Stdlib paths not under either prefix are
|
||||
# left as-is — they reveal only standard OS locations, not deployment structure.
|
||||
install_root = os.path.dirname(settings.BASE_DIR) + os.sep
|
||||
prefixes_to_strip = [install_root]
|
||||
if sys.prefix != sys.base_prefix:
|
||||
venv_root = sys.prefix + os.sep
|
||||
if venv_root != install_root:
|
||||
prefixes_to_strip.append(venv_root)
|
||||
tb = ''.join(traceback.format_exception(exc))
|
||||
for prefix in prefixes_to_strip:
|
||||
tb = re.sub(r'(File ")' + re.escape(prefix), r'\1', tb)
|
||||
return tb
|
||||
if isinstance(exc, TemplateError):
|
||||
parts = [f"{type(exc).__name__}: {exc}"]
|
||||
if getattr(exc, 'name', None):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import io
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.storage import Storage
|
||||
|
|
@ -1200,6 +1203,32 @@ class ConfigTemplateDebugTestCase(TestCase):
|
|||
with self.assertRaises(TemplateSyntaxError):
|
||||
render_jinja2("{% debug %}", {}, debug=False)
|
||||
|
||||
def test_format_render_error_debug_redacts_install_path(self):
|
||||
"""format_render_error() strips the repo install-path prefix from debug tracebacks."""
|
||||
t = ConfigTemplate(name='redact-test', template_code='hello', debug=True)
|
||||
try:
|
||||
raise ValueError("deliberate test error")
|
||||
except ValueError as exc:
|
||||
result = t.format_render_error(exc)
|
||||
install_root = os.path.dirname(settings.BASE_DIR) + os.sep
|
||||
self.assertIn('Traceback', result)
|
||||
self.assertNotIn(install_root, result)
|
||||
# Also verify the venv prefix is stripped when running inside a virtualenv.
|
||||
if sys.prefix != sys.base_prefix:
|
||||
venv_root = sys.prefix + os.sep
|
||||
if venv_root != install_root:
|
||||
self.assertNotIn(venv_root, result)
|
||||
|
||||
def test_format_render_error_non_debug_returns_concise_message(self):
|
||||
"""format_render_error() returns a one-line message (no traceback) when debug=False."""
|
||||
t = ConfigTemplate(name='nodebug-test', template_code='hello', debug=False)
|
||||
try:
|
||||
raise TemplateError("bad template")
|
||||
except TemplateError as exc:
|
||||
result = t.format_render_error(exc)
|
||||
self.assertNotIn('Traceback', result)
|
||||
self.assertIn('TemplateError', result)
|
||||
|
||||
|
||||
class JinjaEnvFilterTestCase(TestCase):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue