Skip to content

S3/Backblaze object keys with '/' are percent-encoded to %2F → wrong resource #120

Description

@AtelyPham

Summary

S3 / Backblaze object keys that contain / (i.e. essentially every real folder-style key, and the bucket separator itself for the path-style amazon-s3 ops) are percent-encoded to %2F by the shared declarative-REST path interpolation, so the request addresses the wrong (non-existent) object. The SigV4 signature is correct (it signs url.pathname verbatim for S3), so AWS accepts the signature and returns NoSuchKey/404 — the resource path is what's wrong, not the auth.

Surfaced while implementing SigV4 (#113 / #118). Pre-existing, but newly load-bearing: before #118 these adapters used Bearer auth and never authenticated, so the path mangling was moot.

Evidence

  • executeRestRequest builds the path via interpolate(request.path, inv.args) (src/connectors/adapters/declarative-rest.ts).
  • interpolate runs encodeURIComponent(String(value)) on each substituted value, turning /%2F.
  • amazon-s3 path-style ops carry bucket+key as a single {key}/{destinationKey} segment (files.read path /{key}, etc.). backblaze keeps {bucket} as its own segment but still mangles intra-key slashes.

Repro

amazonS3Connector.executeRead({ capabilityName: 'files.read', args: { key: 'mybucket/folder/file.txt' }, ... })
// → GET https://s3.<region>.amazonaws.com/mybucket%2Ffolder%2Ffile.txt   (wrong object)

Suggested fix

Render path placeholders with a slash-preserving encoder (encode each segment but leave / intact), distinct from query/header interpolation which should keep encoding /. Because the S3 canonicalUri signs url.pathname verbatim, switching to literal / keeps signing consistent with what's sent. This touches shared declarative-REST path rendering (350+ adapters), so it needs a careful per-path-param policy (raw vs encoded) rather than a blanket change.

Refs #113, #118.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions