Skip to content

Commit

Permalink
resolves asciidoctor#678 allow Kroki server in CSP (asciidoctor#802)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggrossetie authored Oct 12, 2023
1 parent 91ae317 commit d036093
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 96 deletions.
100 changes: 34 additions & 66 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@
"gulp": "^4.0.2",
"lodash.throttle": "4.1.1",
"mathjax": "^2.7.9",
"mocha": "9.2.2",
"mocha": "10.2.0",
"mocha-junit-reporter": "2.2.1",
"mocha-multi-reporters": "1.5.1",
"path-browserify": "1.0.1",
Expand All @@ -655,7 +655,7 @@
"@asciidoctor/core": "2.2.6",
"@asciidoctor/docbook-converter": "2.0.0",
"@orcid/bibtex-parse-js": "0.0.25",
"asciidoctor-kroki": "^0.17.0",
"asciidoctor-kroki": "0.18.1",
"html-entities": "^2.4.0",
"js-yaml": "^4.1.0",
"querystring": "^0.2.1",
Expand Down
45 changes: 30 additions & 15 deletions src/asciidoctorWebViewConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,42 @@ const previewStrings = {
}

/**
* @param webviewResourceProvider
* @param securityLevel
* @param krokiServerUrl
* @param nonce
*/
function getCspForResource (webviewResourceProvider: WebviewResourceProvider, securityLevel: AsciidocPreviewSecurityLevel, nonce: string): string {
function getCspForResource (webviewResourceProvider: WebviewResourceProvider, securityLevel: AsciidocPreviewSecurityLevel, krokiServerUrl: string, nonce: string): string {
if (securityLevel === AsciidocPreviewSecurityLevel.AllowScriptsAndAllContent) {
return '<meta http-equiv="Content-Security-Policy" content="">'
}
const rule = webviewResourceProvider.cspSource
const highlightjsInlineScriptHash = 'sha256-ZrDBcrmObbqhVV/Mag2fT/y08UJGejdW7UWyEsi4DXw='
const rules = {
'default-src': ['\'none\''],
'img-src': ['\'self\'', rule, 'https:', 'data:', krokiServerUrl],
'object-src': ['\'self\'', rule, 'https:', 'data:', krokiServerUrl],
'media-src': ['\'self\'', rule, 'https:', 'data:', krokiServerUrl],
'script-src': [`'nonce-${nonce}'`, `'${highlightjsInlineScriptHash}'`, 'https://*.vscode-cdn.net/'],
'style-src': ['\'self\'', rule, '\'unsafe-inline\'', 'data:'],
'font-src': ['\'self\'', rule, 'https:', 'data:', 'about:'],
}
// add font-src about: as a workaround: https://github.com/mathjax/MathJax/issues/256#issuecomment-37990603
switch (securityLevel) {
case AsciidocPreviewSecurityLevel.AllowInsecureContent:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} http: https: data:; media-src 'self' ${rule} http: https: data:; script-src 'nonce-${nonce}' '${highlightjsInlineScriptHash}' https://*.vscode-cdn.net/; style-src 'self' ${rule} 'unsafe-inline' http: https: data:; font-src 'self' ${rule} http: https: data: about:;">`

case AsciidocPreviewSecurityLevel.AllowInsecureLocalContent:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; media-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:*; script-src 'nonce-${nonce}' '${highlightjsInlineScriptHash}' https://*.vscode-cdn.net/; style-src 'self' ${rule} 'unsafe-inline' https: data: http://localhost:* http://127.0.0.1:*; font-src 'self' ${rule} https: data: http://localhost:* http://127.0.0.1:* about:;">`

case AsciidocPreviewSecurityLevel.AllowScriptsAndAllContent:
return '<meta http-equiv="Content-Security-Policy" content="">'

case AsciidocPreviewSecurityLevel.Strict:
default:
return `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' ${rule} https: data:; media-src 'self' ${rule} https: data:; script-src 'nonce-${nonce}' '${highlightjsInlineScriptHash}' https://*.vscode-cdn.net/; style-src 'self' ${rule} 'unsafe-inline' https: data:; font-src 'self' ${rule} https: data: about:;">`
if (securityLevel === AsciidocPreviewSecurityLevel.AllowInsecureContent) {
// allow "insecure" content (http protocol)
rules['img-src'] = [...rules['img-src'], 'http:']
rules['object-src'] = [...rules['img-src'], 'http:']
rules['media-src'] = [...rules['img-src'], 'http:']
rules['style-src'] = [...rules['img-src'], 'http:']
rules['font-src'] = [...rules['img-src'], 'http:']
} else if (securityLevel === AsciidocPreviewSecurityLevel.AllowInsecureLocalContent) {
rules['img-src'] = [...rules['img-src'], 'http://localhost:*', 'http://127.0.0.1:*']
rules['object-src'] = [...rules['img-src'], 'http://localhost:*', 'http://127.0.0.1:*']
rules['media-src'] = [...rules['img-src'], 'http://localhost:*', 'http://127.0.0.1:*']
rules['style-src'] = [...rules['img-src'], 'http://localhost:*', 'http://127.0.0.1:*']
rules['font-src'] = [...rules['img-src'], 'http://localhost:*', 'http://127.0.0.1:*']
}
return `<meta http-equiv="Content-Security-Policy" content="${Object.entries(rules).map(([key, values]) => `${key} ${values.join(' ')}`).join('; ')}">`
}

function escapeAttribute (value: string | vscode.Uri): string {
Expand Down Expand Up @@ -142,7 +157,7 @@ export class AsciidoctorWebViewConverter {
// Content Security Policy
const nonce = new Date().getTime() + '' + new Date().getMilliseconds()
const webviewResourceProvider = this.webviewResourceProvider
const csp = getCspForResource(webviewResourceProvider, this.securityLevel, nonce)
const csp = getCspForResource(webviewResourceProvider, this.securityLevel, this.krokiServerUrl, nonce)
const syntaxHighlighter = node.$syntax_highlighter()
let assetUriScheme = node.getAttribute('asset-uri-scheme', 'https')
if (assetUriScheme.trim() !== '') {
Expand Down
43 changes: 43 additions & 0 deletions test-workspace/diagrams.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
= Diagrams
:kroki-server-url: http://localhost:8000
// The `kroki-server-url` attribute must be defined as a document attribute
// https://docs.asciidoctor.org/asciidoc/latest/attributes/custom-attributes/ must be placed at the top of the asciidoc file

[plantuml,align=center]
....
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
Alice -> Bob: Another authentication Request
Alice <-- Bob: Another authentication Response
....


[d2,width=450,align=center]
....
D2 Parser: {
shape: class
# Default visibility is + so no need to specify.
+reader: io.RuneReader
readerPos: d2ast.Position
# Private field.
-lookahead: "[]rune"
# Protected field.
# We have to escape the # to prevent the line from being parsed as a comment.
\#lookaheadPos: d2ast.Position
+peek(): (r rune, eof bool)
rewind()
commit()
\#peekn(n int): (s string, eof bool)
}
"github.com/terrastruct/d2parser.git" -> D2 Parser
....


NOTE: We are using a local instance of Kroki!
13 changes: 0 additions & 13 deletions test-workspace/plantuml.adoc

This file was deleted.

0 comments on commit d036093

Please sign in to comment.