From bbfa3b0aa057f7d9c80b6e9bcc11874bee96a584 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 8 May 2026 20:03:48 +0200 Subject: [PATCH] Use validation functions canonically from util --- RNS/Utilities/rngit/pages.py | 7 +++--- RNS/Utilities/rngit/server.py | 46 +---------------------------------- RNS/Utilities/rngit/util.py | 46 +++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/RNS/Utilities/rngit/pages.py b/RNS/Utilities/rngit/pages.py index c59120fa..0de66199 100644 --- a/RNS/Utilities/rngit/pages.py +++ b/RNS/Utilities/rngit/pages.py @@ -37,7 +37,7 @@ import RNS from collections import deque from datetime import datetime from RNS.Utilities.rngit import APP_NAME -from RNS.Utilities.rngit.util import MarkdownToMicron +from RNS.Utilities.rngit.util import MarkdownToMicron, san_sha from RNS.Utilities.rngit.highlight import SyntaxHighlighter from RNS.vendor.configobj import ConfigObj from RNS.vendor import umsgpack as mp @@ -519,7 +519,7 @@ class NomadNetworkNode(): if i == len(path_components) - 1: breadcrumb_parts.append(component) # Last component not a link else: breadcrumb_parts.append(self.m_link(component, self.PATH_TREE, g=group_name, r=repo_name, ref=ref, path=current_path)) - else: breadcrumb_parts.append("") # Could be "root" or something, but a bit confusing + else: breadcrumb_parts.append("") breadcrumb = " / ".join(breadcrumb_parts) nav_parts.append(">>\n" + breadcrumb + "\n") @@ -1658,8 +1658,7 @@ class NomadNetworkNode(): if result.returncode == 0: hash_val = result.stdout.strip() - # Validate it's a 40-char hex string - if len(hash_val) == 40 and all(c in "0123456789abcdef" for c in hash_val.lower()): return hash_val.lower() + return san_sha(hash_val.lower()) except subprocess.TimeoutExpired: RNS.log(f"Timeout resolving ref '{ref}'", RNS.LOG_WARNING) except Exception as e: RNS.log(f"Error resolving ref: {e}", RNS.LOG_WARNING) diff --git a/RNS/Utilities/rngit/server.py b/RNS/Utilities/rngit/server.py index fc92b6af..ea87b9b0 100644 --- a/RNS/Utilities/rngit/server.py +++ b/RNS/Utilities/rngit/server.py @@ -44,6 +44,7 @@ from tempfile import NamedTemporaryFile from RNS._version import __version__ from RNS.Utilities.rngit import APP_NAME from RNS.Utilities.rngit.pages import NomadNetworkNode +from RNS.Utilities.rngit.util import san_ref, san_sha from RNS.vendor.configobj import ConfigObj from RNS.vendor import umsgpack as mp @@ -3101,49 +3102,4 @@ COMMENT_TEMPLATE = "# Remove this line and enter your update. Save and exit when CREATE_DOC_TEMPLATE = "# Remove this line and enter your document content. Save and exit when done, or save an empty document to abort abort." DOC_PERMISSIONS_TEMPLATE ="# No permissions are currently defined for this workdoc. Add them below, and save and exit when you are done." -# Validate ref names according to https://git-scm.com/docs/git-check-ref-format -# This may be a bit overkill, since git validates names as well, but why not. -def san_ref(ref): - if ref.startswith("-"): return None - if ref.startswith("/"): return None - if ref.endswith("/"): return None - if ref.endswith("."): return None - - if " " in ref: return None - if not "/" in ref: return None - if ".." in ref: return None - if "/." in ref: return None - if "//" in ref: return None - if "\\" in ref: return None - - for comp in ref.split("/"): - if comp.endswith(".lock"): return None - - if not all(ord(c) >= 40 for c in ref): return None # Any control character - if "\x7f" in ref: return None # ASCII DEL (177) - if "~" in ref: return None - if "^" in ref: return None - if ":" in ref: return None - if "?" in ref: return None - if "*" in ref: return None - if "[" in ref: return None - if "@{" in ref: return None - if "@" == ref: return None - - return ref - -def san_refs(refs): - if not type(refs) == list: return None - for ref in refs: - if not san_ref(ref): return None - - return refs - -# Git SHA format validation -def san_sha(sha): - if len(sha) < 40: return None - try: bytes.fromhex(sha) - except: return None - return sha - if __name__ == "__main__": main() \ No newline at end of file diff --git a/RNS/Utilities/rngit/util.py b/RNS/Utilities/rngit/util.py index 251e2509..cd712d74 100644 --- a/RNS/Utilities/rngit/util.py +++ b/RNS/Utilities/rngit/util.py @@ -31,6 +31,52 @@ import re import RNS +# Validate ref names according to https://git-scm.com/docs/git-check-ref-format +# This may be a bit overkill, since git validates names as well, but why not. +def san_ref(ref): + RNS.log(f"SAN REF: {ref}") + if ref.startswith("-"): return None + if ref.startswith("/"): return None + if ref.endswith("/"): return None + if ref.endswith("."): return None + + if " " in ref: return None + if not "/" in ref: return None + if ".." in ref: return None + if "/." in ref: return None + if "//" in ref: return None + if "\\" in ref: return None + + for comp in ref.split("/"): + if comp.endswith(".lock"): return None + + if not all(ord(c) >= 40 for c in ref): return None # Any control character + if "\x7f" in ref: return None # ASCII DEL (177) + if "~" in ref: return None + if "^" in ref: return None + if ":" in ref: return None + if "?" in ref: return None + if "*" in ref: return None + if "[" in ref: return None + if "@{" in ref: return None + if "@" == ref: return None + + return ref + +def san_refs(refs): + if not type(refs) == list: return None + for ref in refs: + if not san_ref(ref): return None + + return refs + +# Git SHA format validation +def san_sha(sha): + if len(sha) < 40: return None + try: bytes.fromhex(sha) + except: return None + return sha + class MarkdownToMicron: BOLD = "`!" BOLD_END = "`!"