{"record":{"id":"9feed80ac917508b","repo":"microsoft/aspire","slug":"the-rust-app-resourcename-has-a-cargo-config-argument-that","errorCode":null,"errorMessage":"The Rust app '{resourceName}' has a Cargo --config argument that may contain credentials. Generated Dockerfiles cannot embed credentials; use a hand-written Dockerfile with a BuildKit secret mount instead.","messagePattern":"The Rust app '(.+?)' has a Cargo --config argument that may contain credentials\\. Generated Dockerfiles cannot embed credentials; use a hand-written Dockerfile with a BuildKit secret mount instead\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs","lineNumber":342,"sourceCode":"    private static void ValidateCargoArgumentsDoNotContainCredentials(IReadOnlyList<string> cargoArgs, string resourceName)\n    {\n        for (var i = 0; i < cargoArgs.Count; i++)\n        {\n            string? configuration = null;\n            if (cargoArgs[i] == \"--config\" && i + 1 < cargoArgs.Count)\n            {\n                configuration = cargoArgs[++i];\n            }\n            else if (cargoArgs[i].StartsWith(\"--config=\", StringComparison.Ordinal))\n            {\n                configuration = cargoArgs[i][\"--config=\".Length..];\n            }\n\n            if (configuration is not null\n                && (SensitiveCargoConfigAssignmentPattern().IsMatch(configuration)\n                    || CredentialBearingUrlPattern().IsMatch(configuration)))\n            {\n                throw new DistributedApplicationException(\n                    $\"The Rust app '{resourceName}' has a Cargo --config argument that may contain credentials. \" +\n                    \"Generated Dockerfiles cannot embed credentials; use a hand-written Dockerfile with a BuildKit secret mount instead.\");\n            }\n        }\n    }\n\n    // Cargo accepts configuration as either:\n    //   --config registries.private.token=\"secret\"\n    //   --config=env.PGPASSWORD=\"secret\"\n    // Match only credential-named assignment keys so safe settings such as\n    // `net.git-fetch-with-cli=true` and `registry.credential-provider=...` remain supported.\n    [GeneratedRegex(\n        \"\"\"(?:^|[.{,\\s\"'])(?:PGPASSWORD|MYSQL_PWD|token|password|passwd|secret|credential|api[_-]?key|access[_-]?key|private[_-]?key|client[_-]?secret|connection[_-]?strings?)(?:[\"']?\\s*=)\"\"\",\n        RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)]\n    private static partial Regex SensitiveCargoConfigAssignmentPattern();\n\n    // A URL with user information, in the shape `scheme://userinfo@host/path`, persists\n    // credentials even when the configuration key itself has an ordinary name.","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs#L324-L360","documentation":"Before generating a Dockerfile, the Rust generator checks the Cargo --config argument for credential-bearing content: either a sensitive config assignment (e.g. [registry] token = ...) or a URL pattern carrying credentials (user:token@host). Because the generated Dockerfile would embed the config verbatim, the library refuses to leak secrets and throws this exception.","triggerScenarios":"Calling AddRustApp(...).WithCargoArgs(\"--config\", ...) where the config string matches SensitiveCargoConfigAssignmentPattern or CredentialBearingUrlPattern, e.g. --config 'registries.crates-io.protocol=\"sparse\"' combined with a token, or --config containing 'https://user:token@index.crates.io'.","commonSituations":"Passing a private registry token inline via --config for CI; copying a cargo config that includes a credentials block; embedding net.git-fetch-with-cli credentials in args.","solutions":["Move credentials out of --config into a hand-written Dockerfile that mounts the config as a BuildKit secret (RUN --mount=type=secret,id=cargo-config).","Use environment variables / Docker build secrets (CARGO_REGISTRIES_<NAME>_TOKEN) instead of inline config.","Reference a checked-in, credential-free cargo config.toml file instead of an inline --config string.","Use a pre-built image or cache mount that already has registry auth, so no credentials enter the Dockerfile."],"exampleFix":"// before\n.WithCargoArgs(\"--config\", \"registries.my-registry.token=\\\"ghp_secret123\\\"\")\n// after: hand-written Dockerfile\n// RUN --mount=type=secret,id=cargo-config,target=/root/.cargo/config.toml cargo build --release","handlingStrategy":"validation","validationCode":"static bool ConfigMayContainCredentials(string config) =>\n    config.Contains(\"token\", StringComparison.OrdinalIgnoreCase) ||\n    config.Contains(\"password\", StringComparison.OrdinalIgnoreCase) ||\n    System.Text.RegularExpressions.Regex.IsMatch(config, @\"\\w+:\\w+@\"); // user:pass@host","typeGuard":null,"tryCatchPattern":"try { PublishAsync(); }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"may contain credentials\")) {\n    logger.LogError(\"Move Cargo --config credentials to a BuildKit secret mount\");\n}","preventionTips":["Never inline registry tokens in --config arguments","Use CARGO_REGISTRIES_*_TOKEN environment variables or BuildKit secrets","Keep a credential-free cargo config.toml in source control"],"tags":["security","credentials","cargo","dockerfile"],"backgroundTag":"missing-credentials","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}