elastic / elastic/integrations

[bug-hunter] Proofpoint On Demand websocket cursor corrupts `sinceTime` values containing `+`

Open
#17,875 2 comments 0 reactions 1 assignee Claimed by @efd6 View on GitHub
Integration:proofpoint_on_demand needs:triage Team:Security-Service Integrations
Dominant language
Handlebars
Stars
333
Forks
647
Avg merge
2d 17h
Merged PRs (30d)
225

Description

## Impact
Proofpoint On Demand `message` stream reconnects can request the wrong cursor value when the stored timestamp has a positive timezone offset (for example `+0000`, `+0530`). Because `sinceTime` is concatenated directly into the URL, `+` is interpreted as a space during query parsing. This can cause duplicate ingestion or missed events after reconnect.

## Reproduction Steps
1. Save and run this new minimal repro script:

```python
from urllib.parse import urlparse, parse_qs

base = "(example.test/redacted)
last_timestamp = "2026-03-10T10:00:00.000000+0000"
# Mirrors websocket.yml.hbs logic: state.url+"&sinceTime=" + state.cursor.last_timestamp
actual_url = base + "&sinceTime=" + last_timestamp
parsed = parse_qs(urlparse(actual_url).query)
actual_since = parsed.get("sinceTime", [None])[0]

expected_since = last_timestamp
print("constructed_url:", actual_url)
print("parsed_sinceTime:", repr(actual_since))
print("expected_sinceTime:", repr(expected_since))

if actual_since != expected_since:
print("FAIL: sinceTime changed during query parsing because '+' was not URL-encoded")
raise SystemExit(1)
print("PASS")
```

2. Run:

```bash
python /tmp/gh-aw/agent/repro_proofpoint_since_time.py
```

## Expected vs Actual
**Expected:** `sinceTime` remains `2026-03-10T10:00:00.000000+0000`.

**Actual:** `sinceTime` becomes `2026-03-10T10:00:00.000000 0000` (plus sign decoded as space), and the script exits with status 1.

Actual output:

```text
constructed_url: (example.test/redacted)
parsed_sinceTime: '2026-03-10T10:00:00.000000 0000'
expected_sinceTime: '2026-03-10T10:00:00.000000+0000'
FAIL: sinceTime changed during query parsing because '+' was not URL-encoded
```

## Failing Test
```python
from urllib.parse import urlparse, parse_qs

base = "(example.test/redacted)
last_timestamp = "2026-03-10T10:00:00.000000+0000"
actual_url = base + "&sinceTime=" + last_timestamp
parsed = parse_qs(urlparse(actual_url).query)
actual_since = parsed.get("sinceTime", [None])[0]

assert actual_since == last_timestamp
```

## Evidence
- `packages/proofpoint_on_demand/data_stream/message/agent/stream/websocket.yml.hbs:3-4` concatenates `sinceTime` without URL encoding:
- `state.url+"&sinceTime="+state.cursor.last_timestamp`
- `packages/proofpoint_on_demand/data_stream/message/agent/stream/websocket.yml.hbs:13` stores cursor from event timestamp:
- `"last_timestamp": body.ts`
- `packages/proofpoint_on_demand/data_stream/message/sample_event.json:54` shows timestamp values include timezone offsets in this stream format.

---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/integrations/actions/runs/23242124791)

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on Mar 25, 2026, 11:28 AM UTC

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.