{"record":{"id":"d3e42f081490cebd","repo":"OrchardCMS/OrchardCore","slug":"the-smtp-pickup-directory-location-pickupdirectorylocation","errorCode":null,"errorMessage":"The SMTP pickup directory location '{pickupDirectoryLocation}' resolves outside the configured pickup directory base '{pickupDirectoryLocationBase}'.","messagePattern":"The SMTP pickup directory location '(.+?)' resolves outside the configured pickup directory base '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Email.Smtp/Services/SmtpPickupDirectoryResolver.cs","lineNumber":73,"sourceCode":"\n    public static string ResolvePickupDirectoryLocation(string pickupDirectoryLocationBase, string pickupDirectoryLocation)\n    {\n        ArgumentException.ThrowIfNullOrWhiteSpace(pickupDirectoryLocationBase);\n\n        if (!IsValidPickupDirectoryLocation(pickupDirectoryLocation))\n        {\n            throw new InvalidOperationException(\"The SMTP pickup directory location is invalid.\");\n        }\n\n        var normalizedPickupDirectoryLocation = NormalizePickupDirectoryLocation(pickupDirectoryLocation);\n\n        var fullPickupDirectoryLocation = string.IsNullOrWhiteSpace(normalizedPickupDirectoryLocation)\n            ? pickupDirectoryLocationBase\n            : Path.GetFullPath(Path.Combine(pickupDirectoryLocationBase, normalizedPickupDirectoryLocation));\n\n        if (!IsWithinBasePath(pickupDirectoryLocationBase, fullPickupDirectoryLocation))\n        {\n            throw new InvalidOperationException($\"The SMTP pickup directory location '{pickupDirectoryLocation}' resolves outside the configured pickup directory base '{pickupDirectoryLocationBase}'.\");\n        }\n\n        return fullPickupDirectoryLocation;\n    }\n\n    public static bool IsValidPickupDirectoryLocation(string pickupDirectoryLocation)\n    {\n        if (string.IsNullOrWhiteSpace(pickupDirectoryLocation))\n        {\n            return true;\n        }\n\n        pickupDirectoryLocation = pickupDirectoryLocation.Trim();\n\n        if (pickupDirectoryLocation.IndexOfAny(s_invalidPickupDirectoryLocationCharacters) >= 0 ||\n            pickupDirectoryLocation.Contains(\"{%\", StringComparison.Ordinal))\n        {\n            return false;","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Email.Smtp/Services/SmtpPickupDirectoryResolver.cs#L55-L91","documentation":"After resolving the configured pickup directory location against the base path with Path.GetFullPath/Combine, the resolver verifies the result stays within the base (IsWithinBasePath). If the resolved path escapes the configured base directory, it throws InvalidOperationException to block path traversal.","triggerScenarios":"PickupDirectoryLocation contains traversal segments such as '..' or rooted/absolute paths that, when combined with the base, resolve outside the base directory; the guard throws before returning the path.","commonSituations":"Administrator enters a relative path with '../' segments, or a value pointing at a different drive/root; security-hardened deployments where the base is intentionally locked down and the configured value tries to escape it.","solutions":["Configure a pickup directory location that resolves inside the configured base directory.","Remove '..' segments or absolute paths that escape the base; use subfolders of the base instead.","Update the pickup directory base setting itself if the intended target genuinely lies elsewhere.","Verify the final path stays within the base before saving settings (use the resolver's IsValid/IsWithinBasePath helpers)."],"exampleFix":"// before\n\"PickupDirectoryLocation\": \"..\\\\OtherSite\\\\Pickup\"\n// after\n\"PickupDirectoryLocation\": \"Pickup\" // resolves inside the configured base directory","handlingStrategy":"validation","validationCode":"var full = Path.GetFullPath(Path.Combine(basePath, location));\nif (!full.StartsWith(Path.GetFullPath(basePath), StringComparison.OrdinalIgnoreCase))\n    throw new InvalidOperationException(\"Pickup directory must stay within the configured base.\");","typeGuard":null,"tryCatchPattern":"try { var dir = SmtpPickupDirectoryResolver.ResolvePickupDirectoryLocation(basePath, location); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"outside the configured pickup directory base\")) { /* reject the setting and prompt admin */ }","preventionTips":["Disallow '..' segments and rooted paths in user-supplied directory settings.","Keep configured pickup folders as children of the locked base directory.","Treat this error as a sign of misconfiguration or attempted traversal."],"tags":["email","smtp","path-traversal","security"],"backgroundTag":"path-traversal-blocked","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}