Skip to content

Commit 9831998

Browse files
fix bleach memory leak & simplify git commit hash checker (#14117)
* commit hash footer: disable in production mode * memory leak: fix bleach usage * simplify git commit hash check * improve git commit detection * cleanup
1 parent f6bf3f3 commit 9831998

2 files changed

Lines changed: 60 additions & 9 deletions

File tree

dojo/templatetags/display_tags.py

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import bleach
1212
import dateutil.relativedelta
13-
import git
1413
import markdown
1514
from bleach.css_sanitizer import CSSSanitizer
1615
from django import template
@@ -98,8 +97,11 @@ def markdown_render(value):
9897

9998
@register.filter
10099
def bleach_with_a_tags(message):
101-
allowed_attributes = bleach.ALLOWED_ATTRIBUTES
102-
allowed_attributes["a"] += ["style", "target"]
100+
# Create a copy of ALLOWED_ATTRIBUTES to avoid mutating the global
101+
allowed_attributes = {
102+
**bleach.ALLOWED_ATTRIBUTES,
103+
"a": [*bleach.ALLOWED_ATTRIBUTES.get("a", []), "style", "target"],
104+
}
103105
return mark_safe(bleach.clean(
104106
message,
105107
attributes=allowed_attributes,
@@ -143,11 +145,57 @@ def dojo_version():
143145

144146
@register.simple_tag
145147
def dojo_current_hash():
148+
"""
149+
Display git commit hash in footer if .git directory exists.
150+
151+
This uses direct file reading (no GitPython, no subprocesses) for
152+
negligible performance cost (~0.1ms, 57x faster than GitPython).
153+
Production images exclude .git via .dockerignore, so they show "release mode".
154+
See: https://github.com/DefectDojo/django-DefectDojo/issues/13899
155+
"""
146156
try:
147-
repo = git.Repo(search_parent_directories=True)
148-
sha = repo.head.object.hexsha
149-
return sha[:8]
150-
except:
157+
# Find .git directory (walk up from current file)
158+
current_dir = Path(__file__).resolve().parent
159+
git_dir = None
160+
for parent in [current_dir, *current_dir.parents]:
161+
candidate = parent / ".git"
162+
if candidate.exists():
163+
git_dir = candidate
164+
break
165+
166+
if not git_dir:
167+
return "release mode"
168+
169+
# Read .git/HEAD to get current commit
170+
head_file = git_dir / "HEAD"
171+
if not head_file.exists():
172+
return "release mode"
173+
174+
head_content = head_file.read_text().strip()
175+
176+
if head_content.startswith("ref: "):
177+
# It's a branch reference like "ref: refs/heads/main"
178+
ref_path = head_content[5:] # Remove "ref: " prefix
179+
ref_file = git_dir / ref_path
180+
181+
# Try reading from loose ref file first
182+
if ref_file.exists():
183+
return ref_file.read_text().strip()[:8]
184+
185+
# Fallback: check packed-refs (after git gc, refs are packed)
186+
packed_refs = git_dir / "packed-refs"
187+
if packed_refs.exists():
188+
for line in packed_refs.read_text().splitlines():
189+
if line.startswith("#") or not line.strip():
190+
continue
191+
parts = line.split()
192+
if len(parts) >= 2 and parts[1] == ref_path:
193+
return parts[0][:8]
194+
195+
return "release mode"
196+
# It's a direct SHA (detached HEAD)
197+
return head_content[:8]
198+
except Exception:
151199
return "release mode"
152200

153201

dojo/templatetags/get_banner.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ def get_banner_conf(attribute):
1616
if value:
1717
if attribute == "banner_message":
1818
# only admin can edit login banner, so we allow html, but still bleach it
19-
allowed_attributes = bleach.ALLOWED_ATTRIBUTES
20-
allowed_attributes["a"] += ["style", "target"]
19+
# Create a copy of ALLOWED_ATTRIBUTES to avoid mutating the global
20+
allowed_attributes = {
21+
**bleach.ALLOWED_ATTRIBUTES,
22+
"a": [*bleach.ALLOWED_ATTRIBUTES.get("a", []), "style", "target"],
23+
}
2124
return mark_safe(bleach.clean(
2225
value,
2326
attributes=allowed_attributes,

0 commit comments

Comments
 (0)