From 61f91047e3d0377947250d41fa71c758cb8c2ee8 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Mon, 11 May 2026 14:59:58 -0400 Subject: [PATCH 1/2] Add file system permissions check before install/load --- CHANGELOG.md | 1 + src/cls/IPM/Main.cls | 3 +++ src/cls/IPM/Utils/Module.cls | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a76cc7a1..0c506528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - #973: Enables CORS and JWT configuration for WebApplications in module.xml - #1110: Add `iriscli` and `ipm` container utility scripts that are auto-installed to `~/.local/bin/` and `~/bin/` so they work both inside and outside of containers (Unix/Linux only) - #971: Adds structured test output formats (JSON, YAML, Toon). Use `-f ` for a one-shot override or `config set TestReportFormat ` for a persistent default. Without either, legacy output is shown. Also adds `-output-file` for writing results to a file (including JUnit XML via `.xml` extension) and improves `-quiet` to suppress build noise. +- #1053: Add file system permissions check before install/load. ### Fixed - #1130: Fix issue with ORAS repositories pointing to some OCI registries that require authentication (e.g. ghcr.io) not accepting credentials properly. `repo -list` now shows an `Authenticated?` status for ORAS repos with credentials configured. diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index 3871ecdb..f04380c3 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -2351,6 +2351,9 @@ ClassMethod LoadInternal( set extension = $$$lcase($piece(tDirectoryName,".",*)) if ##class(%File).Exists(tDirectoryName) && ((extension="tgz") || (extension="tar.gz")) { set tTargetDirectory = $$$FileTempDirSys + if '##class(%Library.File).Writeable(tTargetDirectory) { + $$$ThrowStatus($$$ERROR($$$GeneralError, $$$FormatText("Insufficient file system permissions to write to '%1'. Cannot load module from archive.", tTargetDirectory))) + } if $get(pCommandInfo("data", "Verbose")) { write !,"Extracting archive to ",tTargetDirectory } diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index 56bf4059..09c061be 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -226,6 +226,14 @@ ClassMethod LoadModuleFromArchive( try { set tVerbose = $get(pParams("Verbose")) + set ipmBaseDir = ##class(%Library.File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm") + set writeCheckDir = $select(##class(%File).DirectoryExists(ipmBaseDir): ipmBaseDir, 1: ##class(%SYSTEM.Util).DataDirectory()) + if '##class(%Library.File).Writeable(writeCheckDir) { + set msg = $$$FormatText("Insufficient file system permissions to write to '%1'. Cannot install module '%2'.", writeCheckDir, pModuleName) + set tSC = $$$ERROR($$$GeneralError, msg) + quit + } + // Modules have a well-defined location inside the archive set tTargetDirectory = ##class(%Library.File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm/" _ pModuleName _ "/" _ pModuleVersion) if ##class(%File).DirectoryExists(tTargetDirectory) { From a5a6638c899f76324a3aab695ce0cc345192b3d8 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Mon, 11 May 2026 15:15:02 -0400 Subject: [PATCH 2/2] Fix potential issue if temp directory is not createable --- src/cls/IPM/Main.cls | 3 +++ src/cls/IPM/Utils/Module.cls | 1 + 2 files changed, 4 insertions(+) diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index f04380c3..b6b44129 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -2351,6 +2351,9 @@ ClassMethod LoadInternal( set extension = $$$lcase($piece(tDirectoryName,".",*)) if ##class(%File).Exists(tDirectoryName) && ((extension="tgz") || (extension="tar.gz")) { set tTargetDirectory = $$$FileTempDirSys + if tTargetDirectory = ("-" _ -tTargetDirectory) { + $$$ThrowStatus($$$ERROR($$$GeneralError, "Failed to create system temporary directory. Error code: " _ -tTargetDirectory)) + } if '##class(%Library.File).Writeable(tTargetDirectory) { $$$ThrowStatus($$$ERROR($$$GeneralError, $$$FormatText("Insufficient file system permissions to write to '%1'. Cannot load module from archive.", tTargetDirectory))) } diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index 09c061be..902a2dbc 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -226,6 +226,7 @@ ClassMethod LoadModuleFromArchive( try { set tVerbose = $get(pParams("Verbose")) + // Check base IPM install location set ipmBaseDir = ##class(%Library.File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm") set writeCheckDir = $select(##class(%File).DirectoryExists(ipmBaseDir): ipmBaseDir, 1: ##class(%SYSTEM.Util).DataDirectory()) if '##class(%Library.File).Writeable(writeCheckDir) {