diff --git a/Directory.Build.props b/Directory.Build.props index defc4645..63b1b942 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -30,6 +30,6 @@ $(WarningsAsErrors);RS0016;RS0017;RS0026;RS0027;RS0022;RS0023;RS0024;RS0025 - 6.1.16 + 6.1.17 diff --git a/docs/0_de/versioning/002_HISTORY_VERSIONS.MD b/docs/0_de/versioning/002_HISTORY_VERSIONS.MD index f60fc9d8..25bfe419 100644 --- a/docs/0_de/versioning/002_HISTORY_VERSIONS.MD +++ b/docs/0_de/versioning/002_HISTORY_VERSIONS.MD @@ -12,7 +12,7 @@ Heuristik für die Rückwirkungs-Zuordnung: - `docs|test|ci|chore|tooling|refactor|fix` => Patch Aktueller Entwicklungsstand: -- Aktuelle Entwicklungslinie enthält `6.x` (aktueller Arbeitsstand: `v6.1.16`; Details in `docs/versioning/003_CHANGELOG_RELEASES.MD`). +- Aktuelle Entwicklungslinie enthält `6.x` (aktueller Arbeitsstand: `v6.1.17`; Details in `docs/versioning/003_CHANGELOG_RELEASES.MD`). Hinweis: - Die Spalte `Keyword` verwendet den technischen Klassifizierungswert aus der Historie. @@ -20,6 +20,7 @@ Hinweis: | Version | Kurzbeschreibung | Commit | Keyword | |---|---|---|---| +| `6.1.17` | Bridge-/In-Code-Härtung abgeschlossen: `CsCoreRuntimeBridge` strukturell entdoppelt (Tuple-/Assembly-Helper), XML-Dokumentation mit konsistenter deutscher Umlautschreibweise vereinheitlicht und Randfalltests für Delegation/Fallback ergänzt | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.16` | API-Auditierbarkeit fail-closed aktiviert: `Microsoft.CodeAnalysis.PublicApiAnalyzers` zentral eingebunden, Public-API-Baseline (`PublicAPI.Shipped.txt`/`PublicAPI.Unshipped.txt`) für `FileTypeDetectionLib` eingeführt und Governance-/Versioning-Dokumentation um den verbindlichen API-Änderungsprozess erweitert | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.15` | Governance-Drift geschlossen: Branch-Protection-Review-Policy und Scorecard-Governance-Mappings auf den verifizierten Ist-Stand `required_approving_review_count = 0` konsolidiert, inklusive aktualisierter Prozesskontrollen für verpflichtende Required-Checks und Review-Thread-Evidence gemäß `AGENTS.md` | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.14` | 6.1.14 Pipeline-Konvergenz geschlossen: Release-Workflow erzwingt NuGet-Online-Konvergenz jetzt fail-closed auch für `workflow_dispatch`, Release-Metadaten werden artefaktbasiert deterministisch aufgelöst und Fuzzing-Blocker-/Governance-Evidence-Dokumentation entsprechend nachgezogen | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | diff --git a/docs/0_de/versioning/003_CHANGELOG_RELEASES.MD b/docs/0_de/versioning/003_CHANGELOG_RELEASES.MD index 7dc5399b..f98ef029 100644 --- a/docs/0_de/versioning/003_CHANGELOG_RELEASES.MD +++ b/docs/0_de/versioning/003_CHANGELOG_RELEASES.MD @@ -7,6 +7,16 @@ Alle Änderungen werden hier technisch dokumentiert. Die Release-Version selbst ist der Git-Tag `vX.Y.Z` (optional `-prerelease`) als SSOT. +## [6.1.17] +- Added: + - Zwei neue Bridge-Randfalltests für fail-closed Delegation/Fallback (`NormalizeArchiveRelativePath`, `ResolveHmacKeyFromEnvironment`) ergänzt. +- Changed: + - `CsCoreRuntimeBridge` redundanzreduziert: Tuple-Auswertung in dedizierte Helper zentralisiert und Assembly-Pfadauflösung über eine gemeinsame Directory-Probe-Funktion vereinheitlicht. + - In-Code-XML-Dokumentation in Bridge-Kommentaren mit konsistenter deutscher Umlautschreibweise harmonisiert (`Brücke`, `Rückgabe`, `Prüfung`, `Länge`). +- Docs/CI/Tooling: + - Phase-C-Gates lokal erfolgreich ausgeführt: `preflight`, `tests-bdd-coverage`, `api-contract`. + - Versionskonvergenz aktiv auf `6.1.17` gesetzt (`RepoVersion`, `Version`, `PackageVersion`, Versionshistorie DE/EN). + ## [6.1.16] - Added: - `Microsoft.CodeAnalysis.PublicApiAnalyzers` als zentrales Analyzer-Paket aufgenommen und für `FileTypeDetectionLib` aktiviert. diff --git a/docs/1_en/versioning/002_HISTORY_VERSIONS.MD b/docs/1_en/versioning/002_HISTORY_VERSIONS.MD index b2ecdcd4..e27b0480 100644 --- a/docs/1_en/versioning/002_HISTORY_VERSIONS.MD +++ b/docs/1_en/versioning/002_HISTORY_VERSIONS.MD @@ -12,13 +12,14 @@ Heuristics for retroactive classification: - `docs|test|ci|chore|tooling|refactor|fix` => patch Current state: -- Current release line contains `6.x` (current working state: `v6.1.16`; details in `docs/versioning/103_CHANGELOG_RELEASES.MD`). +- Current release line contains `6.x` (current working state: `v6.1.17`; details in `docs/versioning/103_CHANGELOG_RELEASES.MD`). Note: - The \"short description\" column follows the original commit/PR intent text for deterministic traceability and is not normalized to a single language. | Version | Short description | Commit | Keyword | |---|---|---|---| +| `6.1.17` | Bridge and in-code hardening completed: `CsCoreRuntimeBridge` was structurally de-duplicated (tuple/assembly helpers), XML docs were aligned for German-language consistency, and edge-case delegation/fallback tests were added | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.16` | API auditability fail-closed enabled: `Microsoft.CodeAnalysis.PublicApiAnalyzers` was added centrally, a public API baseline (`PublicAPI.Shipped.txt`/`PublicAPI.Unshipped.txt`) was introduced for `FileTypeDetectionLib`, and governance/versioning docs now define the mandatory API-change process | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.15` | Governance drift closed: branch-protection review policy and Scorecard governance mappings were aligned to the verified state `required_approving_review_count = 0`, including updated process controls for mandatory required checks and review-thread evidence per `AGENTS.md` | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.14` | 6.1.14 pipeline convergence closed: release workflow now enforces NuGet online convergence fail-closed for `workflow_dispatch` too, resolves release metadata deterministically via artifact, and aligns fuzzing-blocker/governance evidence documentation | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | diff --git a/docs/1_en/versioning/003_CHANGELOG_RELEASES.MD b/docs/1_en/versioning/003_CHANGELOG_RELEASES.MD index e7715517..7944a44a 100644 --- a/docs/1_en/versioning/003_CHANGELOG_RELEASES.MD +++ b/docs/1_en/versioning/003_CHANGELOG_RELEASES.MD @@ -6,6 +6,16 @@ All changes are documented here in technical terms. The release version itself is the Git tag `vX.Y.Z` (optional `-prerelease`) as SSOT. +## [6.1.17] +- Added: + - Added two bridge edge-case tests for fail-closed delegation/fallback (`NormalizeArchiveRelativePath`, `ResolveHmacKeyFromEnvironment`). +- Changed: + - Reduced redundancy in `CsCoreRuntimeBridge`: tuple mapping is centralized in dedicated helpers and assembly path probing now uses one shared directory-probe function. + - Harmonized in-code XML documentation in bridge comments with consistent German umlaut spelling (`Brücke`, `Rückgabe`, `Prüfung`, `Länge`). +- Docs/CI/Tooling: + - Executed phase-C local gates successfully: `preflight`, `tests-bdd-coverage`, `api-contract`. + - Version convergence set to `6.1.17` (`RepoVersion`, `Version`, `PackageVersion`, DE/EN version history). + ## [6.1.16] - Added: - Added `Microsoft.CodeAnalysis.PublicApiAnalyzers` as a centrally managed analyzer package and enabled it for `FileTypeDetectionLib`. diff --git a/docs/versioning/002_HISTORY_VERSIONS.MD b/docs/versioning/002_HISTORY_VERSIONS.MD index 8f121b7a..544a9385 100644 --- a/docs/versioning/002_HISTORY_VERSIONS.MD +++ b/docs/versioning/002_HISTORY_VERSIONS.MD @@ -12,7 +12,7 @@ Heuristik für die Rückwirkungs-Zuordnung: - `docs|test|ci|chore|tooling|refactor|fix` => Patch Aktueller Entwicklungsstand: -- Aktuelle Entwicklungslinie enthält `6.x` (aktueller Arbeitsstand: `v6.1.16`; Details in `docs/versioning/003_CHANGELOG_RELEASES.MD`). +- Aktuelle Entwicklungslinie enthält `6.x` (aktueller Arbeitsstand: `v6.1.17`; Details in `docs/versioning/003_CHANGELOG_RELEASES.MD`). Hinweis: - Die Spalte `Keyword` verwendet den technischen Klassifizierungswert aus der Historie. @@ -20,6 +20,7 @@ Hinweis: | Version | Kurzbeschreibung | Commit | Keyword | |---|---|---|---| +| `6.1.17` | Bridge-/In-Code-Härtung abgeschlossen: `CsCoreRuntimeBridge` strukturell entdoppelt (Tuple-/Assembly-Helper), XML-Dokumentation mit konsistenter deutscher Umlautschreibweise vereinheitlicht und Randfalltests für Delegation/Fallback ergänzt | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.16` | API-Auditierbarkeit fail-closed aktiviert: `Microsoft.CodeAnalysis.PublicApiAnalyzers` zentral eingebunden, Public-API-Baseline (`PublicAPI.Shipped.txt`/`PublicAPI.Unshipped.txt`) für `FileTypeDetectionLib` eingeführt und Governance-/Versioning-Dokumentation um den verbindlichen API-Änderungsprozess erweitert | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.15` | Governance-Drift geschlossen: Branch-Protection-Review-Policy und Scorecard-Governance-Mappings auf den verifizierten Ist-Stand `required_approving_review_count = 0` konsolidiert, inklusive aktualisierter Prozesskontrollen für verpflichtende Required-Checks und Review-Thread-Evidence gemäß `AGENTS.md` | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.14` | 6.1.14 Pipeline-Konvergenz geschlossen: Release-Workflow erzwingt NuGet-Online-Konvergenz jetzt fail-closed auch für `workflow_dispatch`, Release-Metadaten werden artefaktbasiert deterministisch aufgelöst und Fuzzing-Blocker-/Governance-Evidence-Dokumentation entsprechend nachgezogen | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | diff --git a/docs/versioning/003_CHANGELOG_RELEASES.MD b/docs/versioning/003_CHANGELOG_RELEASES.MD index 333ad8ce..0e34ac9a 100644 --- a/docs/versioning/003_CHANGELOG_RELEASES.MD +++ b/docs/versioning/003_CHANGELOG_RELEASES.MD @@ -7,6 +7,16 @@ Alle Änderungen werden hier technisch dokumentiert. Die Release-Version selbst ist der Git-Tag `vX.Y.Z` (optional `-prerelease`) als SSOT. +## [6.1.17] +- Added: + - Zwei neue Bridge-Randfalltests für fail-closed Delegation/Fallback (`NormalizeArchiveRelativePath`, `ResolveHmacKeyFromEnvironment`) ergänzt. +- Changed: + - `CsCoreRuntimeBridge` redundanzreduziert: Tuple-Auswertung in dedizierte Helper zentralisiert und Assembly-Pfadauflösung über eine gemeinsame Directory-Probe-Funktion vereinheitlicht. + - In-Code-XML-Dokumentation in Bridge-Kommentaren mit konsistenter deutscher Umlautschreibweise harmonisiert (`Brücke`, `Rückgabe`, `Prüfung`, `Länge`). +- Docs/CI/Tooling: + - Phase-C-Gates lokal erfolgreich ausgeführt: `preflight`, `tests-bdd-coverage`, `api-contract`. + - Versionskonvergenz aktiv auf `6.1.17` gesetzt (`RepoVersion`, `Version`, `PackageVersion`, Versionshistorie DE/EN). + ## [6.1.16] - Added: - `Microsoft.CodeAnalysis.PublicApiAnalyzers` als zentrales Analyzer-Paket aufgenommen und für `FileTypeDetectionLib` aktiviert. diff --git a/docs/versioning/102_HISTORY_VERSIONS.MD b/docs/versioning/102_HISTORY_VERSIONS.MD index 1775318f..a18d220c 100644 --- a/docs/versioning/102_HISTORY_VERSIONS.MD +++ b/docs/versioning/102_HISTORY_VERSIONS.MD @@ -12,13 +12,14 @@ Heuristics for retroactive classification: - `docs|test|ci|chore|tooling|refactor|fix` => patch Current state: -- Current release line contains `6.x` (current working state: `v6.1.16`; details in `docs/versioning/103_CHANGELOG_RELEASES.MD`). +- Current release line contains `6.x` (current working state: `v6.1.17`; details in `docs/versioning/103_CHANGELOG_RELEASES.MD`). Note: - The \"short description\" column follows the original commit/PR intent text for deterministic traceability and is not normalized to a single language. | Version | Short description | Commit | Keyword | |---|---|---|---| +| `6.1.17` | Bridge and in-code hardening completed: `CsCoreRuntimeBridge` was structurally de-duplicated (tuple/assembly helpers), XML docs were aligned for German-language consistency, and edge-case delegation/fallback tests were added | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.16` | API auditability fail-closed enabled: `Microsoft.CodeAnalysis.PublicApiAnalyzers` was added centrally, a public API baseline (`PublicAPI.Shipped.txt`/`PublicAPI.Unshipped.txt`) was introduced for `FileTypeDetectionLib`, and governance/versioning docs now define the mandatory API-change process | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.15` | Governance drift closed: branch-protection review policy and Scorecard governance mappings were aligned to the verified state `required_approving_review_count = 0`, including updated process controls for mandatory required checks and review-thread evidence per `AGENTS.md` | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | | `6.1.14` | 6.1.14 pipeline convergence closed: release workflow now enforces NuGet online convergence fail-closed for `workflow_dispatch` too, resolves release metadata deterministically via artifact, and aligns fuzzing-blocker/governance evidence documentation | [unreleased](https://github.com/tomtastisch/FileClassifier/compare/main...HEAD) | patch | diff --git a/docs/versioning/103_CHANGELOG_RELEASES.MD b/docs/versioning/103_CHANGELOG_RELEASES.MD index feeb4fd2..5114544b 100644 --- a/docs/versioning/103_CHANGELOG_RELEASES.MD +++ b/docs/versioning/103_CHANGELOG_RELEASES.MD @@ -6,6 +6,16 @@ All changes are documented here in technical terms. The release version itself is the Git tag `vX.Y.Z` (optional `-prerelease`) as SSOT. +## [6.1.17] +- Added: + - Added two bridge edge-case tests for fail-closed delegation/fallback (`NormalizeArchiveRelativePath`, `ResolveHmacKeyFromEnvironment`). +- Changed: + - Reduced redundancy in `CsCoreRuntimeBridge`: tuple mapping is centralized in dedicated helpers and assembly path probing now uses one shared directory-probe function. + - Harmonized in-code XML documentation in bridge comments with consistent German umlaut spelling (`Brücke`, `Rückgabe`, `Prüfung`, `Länge`). +- Docs/CI/Tooling: + - Executed phase-C local gates successfully: `preflight`, `tests-bdd-coverage`, `api-contract`. + - Version convergence set to `6.1.17` (`RepoVersion`, `Version`, `PackageVersion`, DE/EN version history). + ## [6.1.16] - Added: - Added `Microsoft.CodeAnalysis.PublicApiAnalyzers` as a centrally managed analyzer package and enabled it for `FileTypeDetectionLib`. diff --git a/src/FileTypeDetection/FileTypeDetectionLib.vbproj b/src/FileTypeDetection/FileTypeDetectionLib.vbproj index 018af9ef..d3d31b8a 100644 --- a/src/FileTypeDetection/FileTypeDetectionLib.vbproj +++ b/src/FileTypeDetection/FileTypeDetectionLib.vbproj @@ -7,8 +7,8 @@ true false Tomtastisch.FileClassifier - 6.1.16 - 6.1.16 + 6.1.17 + 6.1.17 tomtastisch Deterministic file type and MIME detection with fail-closed archive safety checks, secure extraction primitives, and reproducible hashing evidence for .NET. filetype;mime;detection;magic-bytes;sniffing;archive;zip;tar;7z;rar;zipslip;security;hashing;sha256;deterministic;dotnet;netstandard2.0;net8;net10 diff --git a/src/FileTypeDetection/Infrastructure/Utils/CsCoreRuntimeBridge.vb b/src/FileTypeDetection/Infrastructure/Utils/CsCoreRuntimeBridge.vb index 6bf59990..ce0d1ddf 100644 --- a/src/FileTypeDetection/Infrastructure/Utils/CsCoreRuntimeBridge.vb +++ b/src/FileTypeDetection/Infrastructure/Utils/CsCoreRuntimeBridge.vb @@ -7,8 +7,8 @@ ' - Variablen im Deklarationsblock, spaltenartig ausgerichtet ' ' Kontext: -' - Runtime-Bruecke fuer optionale Delegation auf C#-CSCore Utilities. -' - Fail-closed: Falls CSCore nicht aufloesbar ist, bleibt VB-Fallback aktiv. +' - Runtime-Brücke für optionale Delegation auf C#-CSCore Utilities. +' - Fail-closed: Falls CSCore nicht auflösbar ist, bleibt VB-Fallback aktiv. ' ============================================================================ Option Strict On @@ -24,12 +24,12 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils ''' ''' Zweck:
- ''' Runtime-Bruecke zwischen VB-Core und optionalem CSCore-Utility-Layer. + ''' Runtime-Brücke zwischen VB-Core und optionalem CSCore-Utility-Layer. '''
''' ''' Fail-Closed:
- ''' - Ist die CSCore-Assembly oder ein erwarteter Typ/Member nicht verfuegbar, - ''' liefert die Bruecke deterministisch False und der VB-Fallback bleibt aktiv. + ''' - Ist die CSCore-Assembly oder ein erwarteter Typ/Member nicht verfügbar, + ''' liefert die Brücke deterministisch False und der VB-Fallback bleibt aktiv. '''
Friend NotInheritable Class CsCoreRuntimeBridge @@ -127,8 +127,8 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Sub ''' - ''' Rueckgabe:
- ''' Laufzeitindikator fuer Unit-Tests und Diagnostik. + ''' Rückgabe:
+ ''' Laufzeitindikator für Unit-Tests und Diagnostik. '''
Friend Shared ReadOnly Property IsCsCoreAvailable As Boolean Get @@ -139,7 +139,7 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils ''' ''' Aktion:
- ''' Setzt die Telemetry-Zaehler zurueck (nur fuer Tests/Diagnostik). + ''' Setzt die Telemetry-Zähler zurück (nur für Tests/Diagnostik). '''
Friend Shared Sub ResetTelemetry() @@ -148,8 +148,8 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Sub ''' - ''' Rueckgabe:
- ''' Liefert eine unveraenderliche Telemetry-Sicht fuer Audit/Tests. + ''' Rückgabe:
+ ''' Liefert eine unveränderliche Telemetry-Sicht für Audit/Tests. '''
Friend Shared Function GetTelemetrySnapshot() As CsCoreRuntimeBridgeTelemetrySnapshot @@ -823,22 +823,21 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils Return False End If - Try - ' Striktes Tuple-Shape: [Boolean, Byte(), String] - isResolved = CBool(values(0)) - key = If(CType(values(1), Byte()), Array.Empty(Of Byte)()) - note = If(CStr(values(2)), String.Empty) - Return True - Catch ex As Exception When _ - TypeOf ex Is InvalidCastException OrElse - TypeOf ex Is NullReferenceException OrElse - TypeOf ex Is IndexOutOfRangeException + ' Striktes Tuple-Shape: [Boolean, Byte(), String] + If Not TryReadHmacResolutionTuple( + OperationResolveHmacKeyFromEnvironment, + values, + isResolved, + key, + note + ) Then isResolved = False key = Array.Empty(Of Byte)() note = String.Empty - RecordFallback(OperationResolveHmacKeyFromEnvironment) Return False - End Try + End If + + Return True End Function Friend Shared Function TryNormalizeArchiveRelativePath _ @@ -873,22 +872,21 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils Return False End If - Try - ' Striktes Tuple-Shape: [Boolean, String, Boolean] - isValid = CBool(values(0)) - normalizedPath = If(CStr(values(1)), String.Empty) - isDirectory = CBool(values(2)) - Return True - Catch ex As Exception When _ - TypeOf ex Is InvalidCastException OrElse - TypeOf ex Is NullReferenceException OrElse - TypeOf ex Is IndexOutOfRangeException + ' Striktes Tuple-Shape: [Boolean, String, Boolean] + If Not TryReadArchivePathTuple( + OperationNormalizeArchiveRelativePath, + values, + isValid, + normalizedPath, + isDirectory + ) Then isValid = False normalizedPath = String.Empty isDirectory = False - RecordFallback(OperationNormalizeArchiveRelativePath) Return False - End Try + End If + + Return True End Function Friend Shared Function TryIsRootPath _ @@ -1200,6 +1198,11 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End SyncLock End Sub + ''' + ''' Auflösung:
+ ''' Ermittelt die CSCore-Assembly deterministisch über geladene Domäne, Assembly-Name + ''' und vertrauenswürdige Basisverzeichnisse. + '''
Private Shared Function ResolveCsCoreAssembly() As Assembly Dim loadedAssemblies() As Assembly @@ -1207,7 +1210,6 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils Dim loadedName As String Dim resolvedAssembly As Assembly Dim assemblyDirectory As String - Dim assemblyPath As String Dim baseDirectoryPath As String resolvedAssembly = Nothing @@ -1229,24 +1231,41 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Try assemblyDirectory = IO.Path.GetDirectoryName(GetType(CsCoreRuntimeBridge).Assembly.Location) - If Not String.IsNullOrWhiteSpace(assemblyDirectory) Then - assemblyPath = IO.Path.Combine(assemblyDirectory, CsCoreAssemblyFileName) - If TryLoadAssemblyFromPath(assemblyPath, resolvedAssembly) Then - Return resolvedAssembly - End If + If TryResolveAssemblyFromDirectory(assemblyDirectory, resolvedAssembly) Then + Return resolvedAssembly End If baseDirectoryPath = AppContext.BaseDirectory - If Not String.IsNullOrWhiteSpace(baseDirectoryPath) Then - assemblyPath = IO.Path.Combine(baseDirectoryPath, CsCoreAssemblyFileName) - If TryLoadAssemblyFromPath(assemblyPath, resolvedAssembly) Then - Return resolvedAssembly - End If + If TryResolveAssemblyFromDirectory(baseDirectoryPath, resolvedAssembly) Then + Return resolvedAssembly End If Return Nothing End Function + ''' + ''' Auflösung:
+ ''' Versucht eine Assembly-Datei aus einem angegebenen Verzeichnis zu laden. + '''
+ Private Shared Function TryResolveAssemblyFromDirectory _ + ( + directoryPath As String, + ByRef resolvedAssembly As Assembly + ) As Boolean + + Dim assemblyPath As String + + resolvedAssembly = Nothing + If String.IsNullOrWhiteSpace(directoryPath) Then Return False + + assemblyPath = IO.Path.Combine(directoryPath, CsCoreAssemblyFileName) + Return TryLoadAssemblyFromPath(assemblyPath, resolvedAssembly) + End Function + + ''' + ''' Ladevorgang:
+ ''' Lädt eine Assembly defensiv über Rohbytes und liefert bei Fehlern deterministisch False. + '''
Private Shared Function TryLoadAssemblyFromPath _ ( assemblyPath As String, @@ -1319,8 +1338,8 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Function ''' - ''' Pruefung:
- ''' Stellt sicher, dass CSCore initialisiert und als verfuegbar markiert ist. + ''' Prüfung:
+ ''' Stellt sicher, dass CSCore initialisiert und als verfügbar markiert ist. '''
Private Shared Function TryEnsureCsCoreAvailable _ ( @@ -1337,8 +1356,8 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Function ''' - ''' Pruefung:
- ''' Fuehrt Verfuegbarkeits- und Methodenguard zusammen und zaehlt Delegation. + ''' Prüfung:
+ ''' Führt Verfügbarkeits- und Methodenguard zusammen und zählt Delegation. '''
Private Shared Function TryPrepareInvocation _ ( @@ -1360,7 +1379,7 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Function ''' - ''' Typisierte Rueckgabe:
+ ''' Typisierte Rückgabe:
''' Invoked Ergebnis muss String sein; sonst fail-closed Fallback. '''
Private Shared Function TryInvokeStringForFallback _ @@ -1388,7 +1407,7 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils End Function ''' - ''' Typisierte Rueckgabe:
+ ''' Typisierte Rückgabe:
''' Invoked Ergebnis muss Integer sein; sonst fail-closed Fallback. '''
Private Shared Function TryInvokeIntegerForFallback _ @@ -1417,7 +1436,7 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils ''' ''' Shape-Guard:
- ''' Invoked Ergebnis muss Object() mit exakt erwarteter Laenge liefern. + ''' Invoked Ergebnis muss Object() mit exakt erwarteter Länge liefern. '''
Private Shared Function TryInvokeObjectArrayForFallback _ ( @@ -1452,7 +1471,7 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils ''' ''' Shape-Guard:
- ''' Invoked Ergebnis muss String() mit exakt erwarteter Laenge liefern. + ''' Invoked Ergebnis muss String() mit exakt erwarteter Länge liefern. '''
Private Shared Function TryInvokeStringArrayForFallback _ ( @@ -1485,6 +1504,72 @@ Namespace Global.Tomtastisch.FileClassifier.Infrastructure.Utils Return True End Function + ''' + ''' Tuple-Guard:
+ ''' Liest das HMAC-Tuple im festen Format + ''' [isResolved(Boolean), key(Byte()), note(String)]. + '''
+ Private Shared Function TryReadHmacResolutionTuple _ + ( + operationName As String, + values() As Object, + ByRef isResolved As Boolean, + ByRef key As Byte(), + ByRef note As String + ) As Boolean + + If values Is Nothing OrElse values.Length <> ExpectedHmacResolutionValuesCount Then + RecordFallback(operationName) + Return False + End If + + Try + isResolved = CBool(values(0)) + key = If(CType(values(1), Byte()), Array.Empty(Of Byte)()) + note = If(CStr(values(2)), String.Empty) + Return True + Catch ex As Exception When _ + TypeOf ex Is InvalidCastException OrElse + TypeOf ex Is NullReferenceException OrElse + TypeOf ex Is IndexOutOfRangeException + RecordFallback(operationName) + Return False + End Try + End Function + + ''' + ''' Tuple-Guard:
+ ''' Liest das Archivpfad-Tuple im festen Format + ''' [isValid(Boolean), normalizedPath(String), isDirectory(Boolean)]. + '''
+ Private Shared Function TryReadArchivePathTuple _ + ( + operationName As String, + values() As Object, + ByRef isValid As Boolean, + ByRef normalizedPath As String, + ByRef isDirectory As Boolean + ) As Boolean + + If values Is Nothing OrElse values.Length <> ExpectedArchivePathValuesCount Then + RecordFallback(operationName) + Return False + End If + + Try + isValid = CBool(values(0)) + normalizedPath = If(CStr(values(1)), String.Empty) + isDirectory = CBool(values(2)) + Return True + Catch ex As Exception When _ + TypeOf ex Is InvalidCastException OrElse + TypeOf ex Is NullReferenceException OrElse + TypeOf ex Is IndexOutOfRangeException + RecordFallback(operationName) + Return False + End Try + End Function + Private Shared Function TryGetClosedGenericMethod _ ( genericMethodDefinition As MethodInfo, diff --git a/tests/FileTypeDetectionLib.Tests/Unit/CsCoreUtilityBridgeUnitTests.cs b/tests/FileTypeDetectionLib.Tests/Unit/CsCoreUtilityBridgeUnitTests.cs index 1179e5b2..fa2900ec 100644 --- a/tests/FileTypeDetectionLib.Tests/Unit/CsCoreUtilityBridgeUnitTests.cs +++ b/tests/FileTypeDetectionLib.Tests/Unit/CsCoreUtilityBridgeUnitTests.cs @@ -203,6 +203,84 @@ public void BridgeTelemetry_TracksDelegationOrFallback_ForHashAndMaterialization } } + [Fact] + public void Bridge_NormalizeArchiveRelativePath_InvalidTraversal_RemainsFailClosed() + { + CsCoreRuntimeBridge.ResetTelemetry(); + + var isValid = true; + var normalizedPath = "seed"; + var isDirectory = true; + + var bridgeCall = CsCoreRuntimeBridge.TryNormalizeArchiveRelativePath( + "../escape.txt", + allowDirectoryMarker: false, + ref isValid, + ref normalizedPath, + ref isDirectory); + + var snapshot = CsCoreRuntimeBridge.GetTelemetrySnapshot(); + if (snapshot.IsCsCoreAvailable) + { + Assert.True(bridgeCall); + Assert.False(isValid); + Assert.Equal(string.Empty, normalizedPath); + Assert.False(isDirectory); + Assert.True(snapshot.GetDelegatedCount("NormalizeArchiveRelativePath") > 0); + return; + } + + Assert.False(bridgeCall); + Assert.False(isValid); + Assert.Equal(string.Empty, normalizedPath); + Assert.False(isDirectory); + Assert.True(snapshot.GetFallbackCount("NormalizeArchiveRelativePath") > 0); + } + + [Fact] + public void Bridge_ResolveHmacKeyFromEnvironment_InvalidBase64_RemainsDeterministic() + { + CsCoreRuntimeBridge.ResetTelemetry(); + + const string environmentVariableName = "FILECLASSIFIER_BRIDGE_TEST_HMAC_B64"; + var original = Environment.GetEnvironmentVariable(environmentVariableName); + try + { + Environment.SetEnvironmentVariable(environmentVariableName, "invalid-base64"); + + var isResolved = false; + var key = Array.Empty(); + var note = string.Empty; + + var bridgeCall = CsCoreRuntimeBridge.TryResolveHmacKeyFromEnvironment( + environmentVariableName, + ref isResolved, + ref key, + ref note); + + var snapshot = CsCoreRuntimeBridge.GetTelemetrySnapshot(); + if (snapshot.IsCsCoreAvailable) + { + Assert.True(bridgeCall); + Assert.False(isResolved); + Assert.Empty(key); + Assert.Contains("invalid Base64", note, StringComparison.Ordinal); + Assert.True(snapshot.GetDelegatedCount("ResolveHmacKeyFromEnvironment") > 0); + return; + } + + Assert.False(bridgeCall); + Assert.False(isResolved); + Assert.Empty(key); + Assert.Equal(string.Empty, note); + Assert.True(snapshot.GetFallbackCount("ResolveHmacKeyFromEnvironment") > 0); + } + finally + { + Environment.SetEnvironmentVariable(environmentVariableName, original); + } + } + private static byte[] CreateOpenDocumentPackage(string mimeType) { using var ms = new MemoryStream();