bfh_export_pdf() og
bfh_create_export_session() eksponerer to parametre der
kører caller-supplied kode/templates. Begge er legitime
for proprietære fonts og organisationsspecifikke templates, men begge
kræver eksplicit trust:
| Parameter | Hvad det gør | Risiko ved misbrug |
|---|---|---|
inject_assets |
Kalder en R-callback med skrive-adgang til template-mappen | Vilkårlig R-kode-eksekvering |
template_path |
Erstatter den pakkede Typst-template | Vilkårlig Typst (kan læse/skrive paths under compilation) |
Begge parametre skal behandles med samme tillidskontrakt som
source(): aldrig fra user-input, altid fra
code-reviewed organisationskontrolleret kilde.
font_path for de fleste tilfældeHvis du kun har brug for at injicere fonts, brug
font_path i stedet for inject_assets. Det er
sikkert at videresende fra konfiguration eller miljøvariable, og kræver
ikke trust på samme niveau:
library(BFHcharts)
# Fonts er statiske filer på disk — ingen kode-eksekvering
bfh_export_pdf(result, "rapport.pdf",
font_path = "/etc/bfh-fonts"
)font_path videregives som --font-path til
Typst-compileren. Typst læser fonts fra mappen men eksekverer ingen kode
fra den.
inject_assets — kun til organisations-kontrolleret
kodeBrug inject_assets når du har dynamiske
filsystem-operationer der ikke passer ind i en fast
font_path-mappe. Eksempel: en privat pakke der bundler
fonts og afpakker dem til template-mappen lige før compilation.
# Sikkert: callback fra code-reviewed privat pakke
inject_my_org_assets <- function(template_dir) {
font_dir <- file.path(template_dir, "fonts")
dir.create(font_dir, showWarnings = FALSE)
file.copy(
system.file("fonts", "Mari", package = "MyOrgPrivateFonts"),
font_dir,
recursive = TRUE
)
}
bfh_export_pdf(result, "rapport.pdf",
inject_assets = inject_my_org_assets
)# FARLIGT: callback bygget fra Shiny-input
server <- function(input, output, session) {
output$pdf <- downloadHandler(
content = function(file) {
# ALDRIG videresend user-supplied kode/strenge til inject_assets:
user_callback <- parse_user_input(input$user_callback)
bfh_export_pdf(result, file, inject_assets = user_callback)
}
)
}Sidstnævnte mønster konverterer en Shiny-input til en eksekverbar callback — hvilket giver brugeren vilkårlig kode-eksekvering på serveren. Kald den “remote code execution” eller “RCE”: uacceptabel selv i interne enterprise deployments.
template_path — kun til organisations-kontrolleret
TypstTilsvarende: template_path peger på en
.typ-fil som Typst-compileren kører. En custom template kan
udføre filsystem-operationer under compilation — så
aldrig modtag template-stien fra user-input.
Siden BFHcharts 0.16.0 kræver custom-template
eksplicit opt-out via restrict_template = FALSE. Default er
TRUE (production-safe). Callers der ikke eksplicit
opt-outer modtager en valideringsfejl ved kald-tid.
# Sikkert: template fra organisations-repo, code-reviewed
bfh_export_pdf(result, "rapport.pdf",
template_path = system.file(
"templates", "afdelings-template.typ",
package = "MyOrgTemplates"
),
restrict_template = FALSE # eksplicit opt-out paakraevet siden 0.16.0
)# FARLIGT: template-sti fra user upload
template <- input$uploaded_template$datapath
bfh_export_pdf(result, "rapport.pdf",
template_path = template
)Den uploadede .typ-fil eksekveres af Typst-compileren
med samme privilege som R-processen. Vilkårlig Typst-kode kan læse og
skrive filsystem-paths.
Hvis dit Shiny-interface skal lade brugere vælge mellem forhåndsgodkendte templates, validér mod en fixed allow-list før kald:
APPROVED_TEMPLATES <- list(
standard = system.file("templates/standard.typ", package = "MyOrg"),
klinisk = system.file("templates/klinisk.typ", package = "MyOrg"),
forskning = system.file("templates/forskning.typ", package = "MyOrg")
)
server <- function(input, output, session) {
output$pdf <- downloadHandler(
content = function(file) {
# User vælger fra dropdown med navn — ikke fil-sti
template <- APPROVED_TEMPLATES[[input$template_name]]
if (is.null(template) || !file.exists(template)) {
stop("Ugyldig template valgt")
}
bfh_export_pdf(result, file,
template_path = template,
restrict_template = FALSE)
}
)
}UI komponenten viser kun navnene fra allow-listen — fil-stier eksponeres aldrig.
bfh_create_export_session()For mange eksporter med identiske template-assets: brug session for
at undgå gentaget I/O. Trust-kravet for inject_assets er
det samme:
session <- bfh_create_export_session(
font_path = "/etc/bfh-fonts",
inject_assets = inject_my_org_assets # Code-reviewed callback
)
on.exit(close(session))
for (afdeling in afdelinger) {
result <- bfh_qic(data_per_afd[[afdeling]], ...)
bfh_export_pdf(result, paste0(afdeling, ".pdf"),
batch_session = session,
metadata = list(department = afdeling)
)
}inject_assets kaldes én gang ved
session-opret; assets deles på tværs af alle eksporter. Trust-kravet er
det samme som single-call mode.
Hvis font_path ikke matcher Typst’s font-lookup, falder
den tilbage på system-fonts (medmindre
ignore_system_fonts = TRUE, default fra v0.10.0). Anbefalet
praksis i production:
Med ignore_system_fonts = TRUE bruger Typst kun fonts
fra font_path plus de bundle’de template-fonts. Det
forhindrer overraskende rendering-forskelle mellem dev-maskiner og
production-deployments hvor system-font-versioner divergerer.
Før dit Shiny app eller batch-script går i produktion:
Som defense-in-depth emitter
bfh_generate_analysis(use_ai = TRUE) en
message() umiddelbart inden kald til
BFHllm::bfhllm_spc_suggestion(). Beskeden bærer det stabile
tag [BFHcharts/AI] og navngiver de felter der
transmitteres, så R-level logs kan bekræfte om og hvornår AI-stien blev
taget. Sæt
options(BFHcharts.suppress_ai_audit_message = TRUE) for at
undertrykke beskeden (f.eks. i applikationer der har egen
audit-trail).
vignette("chart-types") — vælg charttype før
eksport?bfh_export_pdf — \section{Security} med
fuld trust-rationale?bfh_create_export_session — batch-session security
notefont_path for de fleste tilfældeinject_assets
— kun til organisations-kontrolleret kodetemplate_path
— kun til organisations-kontrolleret Typstbfh_create_export_session()