{"record":{"id":"c890cb23724f4f9e","repo":"Tencent/WeKnora","slug":"unsafe-oss-endpoint-w","errorCode":null,"errorMessage":"unsafe OSS endpoint: %w","messagePattern":"unsafe OSS endpoint: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/oss.go","lineNumber":38,"sourceCode":"\t\"github.com/google/uuid\"\n)\n\n// ossFileService implements the FileService interface for Aliyun OSS\n// using the official Aliyun OSS SDK v2 (github.com/aliyun/alibabacloud-oss-go-sdk-v2).\ntype ossFileService struct {\n\tclient         *oss.Client\n\ttempClient     *oss.Client\n\tpathPrefix     string\n\tbucketName     string\n\ttempBucketName string\n}\n\nconst ossScheme = \"oss://\"\n\n// newOSSClient creates an OSS client using the official Aliyun SDK v2.\nfunc newOSSClient(endpoint, region, accessKey, secretKey string) (*oss.Client, error) {\n\tif err := utils.ValidateURLForSSRF(endpoint); err != nil {\n\t\treturn nil, fmt.Errorf(\"unsafe OSS endpoint: %w\", err)\n\t}\n\tcreds := credentials.NewStaticCredentialsProvider(accessKey, secretKey, \"\")\n\n\tcfg := oss.LoadDefaultConfig().\n\t\tWithCredentialsProvider(creds).\n\t\tWithRegion(region).\n\t\tWithEndpoint(endpoint).\n\t\tWithHttpClient(utils.NewSSRFSafeHTTPClient(utils.DefaultSSRFSafeHTTPClientConfig()))\n\n\treturn oss.NewClient(cfg), nil\n}\n\n// ossEnsureBucket checks if the bucket exists and creates it if missing.\nfunc ossEnsureBucket(client *oss.Client, bucketName string) error {\n\texists, err := client.IsBucketExist(context.Background(), bucketName)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to check OSS bucket: %w\", err)\n\t}","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/oss.go#L20-L56","documentation":"newOSSClient runs utils.ValidateURLForSSRF on the endpoint before building the Aliyun OSS client; if the endpoint URL fails the SSRF safety validation (e.g. points at localhost, private/link-local IPs, or is not a valid http(s) URL) the client is not created and this error wraps the validation failure. It is a deliberate security guard, not a connectivity failure.","triggerScenarios":"Constructing an OSS client (via NewOssFileServiceWithTempBucket, CheckOssConnectivity, or config init) with endpoint set to http://127.0.0.1:9000, http://localhost, 169.254.x.x metadata addresses, or a non-URL string.","commonSituations":"Local MinIO/OSS-emulator endpoints in dev configs that pass a deploy-time SSRF check; user-supplied endpoint from a request or DB row; env var typos (OSS_ENDPOINT=127.0.0.1); unit tests explicitly asserting unsafe endpoints are rejected.","solutions":["Set the endpoint to the official public OSS endpoint (e.g. https://oss-cn-hangzhou.aliyuncs.com) over https","If a private/internal endpoint is genuinely required, use the officially allowed internal endpoint form so the SSRF validator accepts it (not raw loopback/link-local IPs)","Fix env/config: ensure OSS_ENDPOINT is a valid absolute http(s) URL with hostname, not an IP or bare hostname like 'localhost'","If the check wrongly rejects a legitimate endpoint, update utils.ValidateURLForSSRF's allowlist rather than bypassing validation"],"exampleFix":"// before\nclient, err := newOSSClient(\"http://127.0.0.1:9000\", region, ak, sk) // rejected: unsafe OSS endpoint\n// after\nclient, err := newOSSClient(\"https://oss-cn-hangzhou.aliyuncs.com\", region, ak, sk)","handlingStrategy":"validation","validationCode":"endpoint := os.Getenv(\"OSS_ENDPOINT\")\nu, err := url.Parse(endpoint)\nif err != nil || (u.Scheme != \"https\" && u.Scheme != \"http\") || u.Host == \"\" {\n    return fmt.Errorf(\"OSS_ENDPOINT must be an absolute http(s) URL, got %q\", endpoint)\n}\nhost := u.Hostname()\nif host == \"localhost\" || net.ParseIP(host) != nil {\n    return fmt.Errorf(\"OSS_ENDPOINT must not be loopback/raw IP: %q\", endpoint)\n}","typeGuard":null,"tryCatchPattern":"client, err := newOSSClient(endpoint, region, ak, sk)\nif err != nil {\n    return fmt.Errorf(\"refusing to start with endpoint %q (SSRF check): %w\", endpoint, err)\n}","preventionTips":["Keep OSS_ENDPOINT in env/config as an official https OSS endpoint, never localhost or raw IPs","Run the SSRF validation as a startup config check so bad endpoints fail fast","If dev needs a local emulator, use a documented allowlist mechanism instead of bypassing validation","Never build endpoints from untrusted user input without validation"],"tags":["oss","aliyun","ssrf","security","config"],"backgroundTag":"unsafe-endpoint-rejected","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}