a2aproject / a2aproject/a2a-js

[Bug]: Timestamp fields are unvalidated strings and are never normalized to UTC

Aperta
#641 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
TypeScript
Stelle
613
Fork
169
Merge medio
1g 6h
PR unite (30g)
21

Descrizione

### What happened?

`google.protobuf.Timestamp` fields are passed straight through as strings. The generated
code is:

```ts
timestamp: isSet(object.timestamp) ? globalThis.String(object.timestamp) : undefined,
```

and `toJSON` copies it back out unchanged. Nothing parses it and nothing checks it, which
causes two separate problems.

**Malformed timestamps are accepted and forwarded.** Every one of these is stored and
re-emitted verbatim:

```js
import { TaskStatus } from '@a2a-js/sdk';
const ts = (t) => TaskStatus.toJSON(TaskStatus.fromJSON({ state: 'TASK_STATE_WORKING', timestamp: t }));

ts('not-a-timestamp'); // { state: 'TASK_STATE_WORKING', timestamp: 'not-a-timestamp' }
ts(''); // { ..., timestamp: '' }
ts(12345); // { ..., timestamp: '12345' } a JSON number becomes a string
```

`a2a-python` rejects all of them. So a JS server accepts a `Task` whose
`status.timestamp` is arbitrary text, hands it downstream, and the Python peer is the one
that throws. The component that let the bad data in isn't the component that reports it,
which makes this annoying to track down in a mixed deployment.

**Offsets are never normalized.** proto3 JSON output is always Z-normalized.
`a2a-python` does that; this SDK keeps whatever offset arrived:

```
input "2026-01-01T05:30:00+05:30"
python "2026-01-01T00:00:00Z"
js "2026-01-01T05:30:00+05:30"
```

Same instant, different bytes. That's fine until something compares bytes rather than
instants, which is what canonicalization does. `src/signature.ts:188` canonicalizes via
`AgentCard.toJSON(AgentCard.fromJSON(card))`, so this codec sits on the signing path.

Storing the field unparsed also means any timestamp comparison or ordering inside the SDK
is operating on a string whose format isn't guaranteed.

### What I'd expect

`fromJSON` parses and validates RFC 3339, rejecting input that isn't a timestamp, and
`toJSON` emits the Z-normalized form.

### How this was found

Round-tripping a shared corpus through this SDK and `a2a-python` and diffing the JSON.
Both generate from the same `.proto`.

Reproduced on `@a2a-js/sdk` 1.0.1 from npm and on `main` at `1c6eb32`, against
`a2a-python` at `cff6727`.

Same question as the other codec issues I'm filing: this is in the generated
`src/types/pb/a2a.ts`, so tell me where you'd like the fix and I'll send it.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.