utils/visualize_graph.py:214 (graph JSON), :135 and :201 (title)
The graph payload is inlined into a <script> block via json.dumps. json.dumps escapes quotes and backslashes but not /, so any node name or file path containing the literal </script> closes the script element early and everything after it is parsed as markup.
Reproduction
$ .venv/bin/python -c "
from codegraphcontext.utils.visualize_graph import build_graph_data, open_in_browser
import tempfile, pathlib
nodes=[{'id':1,'label':'Function','name':'x</script><script>alert(1)</script>','file_path':'/a.py'}]
p = open_in_browser(build_graph_data(nodes, []), title='t',
output_path=str(pathlib.Path(tempfile.mkdtemp())/'g.html'))
html = pathlib.Path(p).read_text()
print('script-breakout present:', '</script><script>alert(1)' in html)
"
script-breakout present: True
The rendered document contains the closing tag verbatim inside what was meant to be a JSON string literal:
"name": "x</script><script>alert(1)</script>",
title is interpolated unescaped at :135 and :201 as well.
Impact
Mostly a robustness problem: a node whose name contains </script> breaks the offline visualization page entirely (blank or malformed graph) with no indication why. Minified or bundled JS, HTML templates and test fixtures containing that string are all realistic sources — CGC already indexes .js and .html files, and this repo itself ships website/public/wasm/*.js.
It is also a genuine (if low-reach) injection: indexing an untrusted repository and opening the generated page executes markup from that repository's identifiers in the local browser.
Suggested fix
Escape </>/& in the serialized JSON before inlining — the standard treatment is replacing < with < (and / in </ with <\/) after json.dumps. HTML-escape title at both interpolation sites.
Environment
|
|
| Commit |
c0e0bed (main) |
| Python |
3.12.3, Linux |
Reproduced with the snippet above.
utils/visualize_graph.py:214(graph JSON),:135and:201(title)The graph payload is inlined into a
<script>block viajson.dumps.json.dumpsescapes quotes and backslashes but not/, so any node name or file path containing the literal</script>closes the script element early and everything after it is parsed as markup.Reproduction
The rendered document contains the closing tag verbatim inside what was meant to be a JSON string literal:
titleis interpolated unescaped at:135and:201as well.Impact
Mostly a robustness problem: a node whose name contains
</script>breaks the offline visualization page entirely (blank or malformed graph) with no indication why. Minified or bundled JS, HTML templates and test fixtures containing that string are all realistic sources — CGC already indexes.jsand.htmlfiles, and this repo itself shipswebsite/public/wasm/*.js.It is also a genuine (if low-reach) injection: indexing an untrusted repository and opening the generated page executes markup from that repository's identifiers in the local browser.
Suggested fix
Escape
</>/&in the serialized JSON before inlining — the standard treatment is replacing<with<(and/in</with<\/) afterjson.dumps. HTML-escapetitleat both interpolation sites.Environment
c0e0bed(main)Reproduced with the snippet above.