Fix path injection, sensitive attribute exposure, and error body truncation
Some checks failed
Endpoint Sync Check / check-drift (push) Successful in 50s
CI / build (push) Failing after 1m26s

Security fixes from audit:

- Escape user-supplied strings (ext_relation_id, interface_name) with
  url.PathEscape before interpolating into API URL paths, preventing
  path traversal via crafted values like "../admin" or "foo/bar"
- Mark auth token URL attributes as Sensitive in both
  virtfusion_user_auth_token and virtfusion_user_server_auth_token
  resources, since the URL embeds the signed token
- Truncate raw API error response bodies to 500 bytes in error messages
  to prevent leaking sensitive data from verbose Laravel error responses

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-16 02:07:34 -04:00
parent 6b7430b67b
commit ef8fbd530b
7 changed files with 30 additions and 13 deletions

View File

@@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/url"
"terraform-provider-virtfusion/internal/client"
@@ -137,7 +138,7 @@ func (r *UserResource) Read(ctx context.Context, req resource.ReadRequest, resp
return
}
result, err := r.client.Get(ctx, fmt.Sprintf("/users/%s/byExtRelation", data.ExtRelationID.ValueString()))
result, err := r.client.Get(ctx, fmt.Sprintf("/users/%s/byExtRelation", url.PathEscape(data.ExtRelationID.ValueString())))
if err != nil {
var apiErr *client.APIError
if errors.As(err, &apiErr) && apiErr.IsNotFound() {
@@ -175,7 +176,7 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
Email: data.Email.ValueString(),
}
result, err := r.client.Put(ctx, fmt.Sprintf("/users/%s/byExtRelation", data.ExtRelationID.ValueString()), body)
result, err := r.client.Put(ctx, fmt.Sprintf("/users/%s/byExtRelation", url.PathEscape(data.ExtRelationID.ValueString())), body)
if err != nil {
resp.Diagnostics.AddError("Error updating user", err.Error())
return
@@ -203,7 +204,7 @@ func (r *UserResource) Delete(ctx context.Context, req resource.DeleteRequest, r
return
}
_, err := r.client.Delete(ctx, fmt.Sprintf("/users/%s/byExtRelation", data.ExtRelationID.ValueString()))
_, err := r.client.Delete(ctx, fmt.Sprintf("/users/%s/byExtRelation", url.PathEscape(data.ExtRelationID.ValueString())))
if err != nil {
var apiErr *client.APIError
if errors.As(err, &apiErr) && apiErr.IsNotFound() {