Commit 2df39252c0
Verified · cmc
Layout: unified · split
Threat-Model.org +24
| @@ -71,6 +71,30 @@ webhook dialer re-checks at connect time so a DNS answer that changes | ||
| 71 | 71 | after validation still cannot reach private space. Redirects are never |
| 72 | 72 | followed. |
| 73 | 73 | |
| 74 | * Rendering pushed markup | |
| 75 | ||
| 76 | Rendered markup is attacker-controlled: a README, a wiki page and a | |
| 77 | profile's about text are all whatever someone pushed or typed. The risk | |
| 78 | is not only what the output contains but what the *parser* is willing to | |
| 79 | go and fetch — the filesystem counterpart of the SSRF guard above. | |
| 80 | ||
| 81 | Org is rendered by go-org, whose default configuration resolves | |
| 82 | =#+INCLUDE:= and =#+SETUPFILE:= targets with =os.ReadFile=. Both are | |
| 83 | refused outright (=orgConfig()= in =internal/httpd=): the file is never | |
| 84 | opened and the keyword stays the inert text it already was, so the rest | |
| 85 | of the document renders normally. There is no safe subset to allow | |
| 86 | instead — an absolute path skips go-org's relative-path join, a relative | |
| 87 | one resolves against the daemon's working directory, and the content | |
| 88 | came from a git object rather than a checkout, so there is no directory | |
| 89 | to scope a read to. Markdown is goldmark, which has no include | |
| 90 | mechanism. go-org's parse warnings are discarded rather than logged, so | |
| 91 | pushed content cannot write to the server's log. | |
| 92 | ||
| 93 | Org output is then sanitized (bluemonday UGC policy) because go-org | |
| 94 | passes raw HTML through — export blocks and inline export snippets — | |
| 95 | while goldmark drops it and needs no pass. The policy admits chroma's | |
| 96 | short token classes and nothing else. | |
| 97 | ||
| 74 | 98 | * Web responses |
| 75 | 99 | |
| 76 | 100 | Every response carries =Content-Security-Policy= (no scripts, no plugins, |